#include "math.h"
#include "io.h"
#include "system.h"

#ifdef HARD_MATH
#define HARD_MUL
#define HARD_SFDIV
#define HARD_FDIV
#define HARD_SFMUL
#define HARD_FMUL
#endif

#define divnorm(num, den, sign) 		\
{						\
  if (num < 0) 					\
    {						\
      num = -num;				\
      sign = 1;					\
    }						\
  else 						\
    {						\
      sign = 0;					\
    }						\
						\
  if (den < 0) 					\
    {						\
      den = - den;				\
      sign = 1 - sign;				\
    } 						\
}


/* The type of the result of a floating point comparison.  This must
   match `__libgcc_cmp_return__' in GCC for the target.  */
/// typedef int __gcc_CMPtype __attribute__ ((mode (__libgcc_cmp_return__)));
/// #define CMPtype __gcc_CMPtype

#define _FP_MUL_MEAT_S(R,X,Y)               \
  _FP_MUL_MEAT_1_wide(_FP_WFRACBITS_S,R,X,Y,umul_ppmm)
#define _FP_MUL_MEAT_D(R,X,Y)               \
  _FP_MUL_MEAT_2_wide(_FP_WFRACBITS_D,R,X,Y,umul_ppmm)
#define _FP_MUL_MEAT_Q(R,X,Y)               \
  _FP_MUL_MEAT_4_wide(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm)

#define _FP_DIV_MEAT_S(R,X,Y)   _FP_DIV_MEAT_1_loop(S,R,X,Y)
#define _FP_DIV_MEAT_D(R,X,Y)   _FP_DIV_MEAT_2_udiv(D,R,X,Y)
#define _FP_DIV_MEAT_Q(R,X,Y)   _FP_DIV_MEAT_4_udiv(Q,R,X,Y)

/* According to RTABI, QNAN is only with the most significant bit of the
   significand set, and all other significand bits zero.  */
#define _FP_NANFRAC_H       _FP_QNANBIT_H
#define _FP_NANFRAC_S       _FP_QNANBIT_S
#define _FP_NANFRAC_D       _FP_QNANBIT_D, 0
#define _FP_NANFRAC_Q       _FP_QNANBIT_Q, 0, 0, 0
#define _FP_NANSIGN_H       0
#define _FP_NANSIGN_S       0
#define _FP_NANSIGN_D       0
#define _FP_NANSIGN_Q       0

#define _FP_KEEPNANFRACP 1
#define _FP_QNANNEGATEDP 0


/* Someone please check this.  */
#define _FP_CHOOSENAN(fs, wc, R, X, Y, OP)              \
  do {                                                  \
    if ((_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs)  \
    && !(_FP_FRAC_HIGH_RAW_##fs(Y) & _FP_QNANBIT_##fs)) \
      {                                                 \
    R##_s = Y##_s;                                      \
    _FP_FRAC_COPY_##wc(R,Y);                            \
      }                                                 \
    else                                                \
      {                                                 \
    R##_s = X##_s;                                      \
    _FP_FRAC_COPY_##wc(R,X);                            \
      }                                                 \
    R##_c = FP_CLS_NAN;                                 \
  } while (0)

#define _FP_TININESS_AFTER_ROUNDING 0




/* Define ALIASNAME as a strong alias for NAME.  */
# define strong_alias(name, aliasname) _strong_alias(name, aliasname)
# define _strong_alias(name, aliasname) \
  extern __typeof (name) aliasname __attribute__ ((alias (#name)));

/* Allow sfp-machine to have its own byte order definitions. */


#define _FP_WORKBITS		3
#define _FP_WORK_LSB		((_FP_W_TYPE)1 << 3)
#define _FP_WORK_ROUND		((_FP_W_TYPE)1 << 2)
#define _FP_WORK_GUARD		((_FP_W_TYPE)1 << 1)
#define _FP_WORK_STICKY		((_FP_W_TYPE)1 << 0)

#ifndef FP_RND_NEAREST
# define FP_RND_NEAREST		0
# define FP_RND_ZERO		1
# define FP_RND_PINF		2
# define FP_RND_MINF		3
#endif
#ifndef FP_ROUNDMODE
# define FP_ROUNDMODE		FP_RND_NEAREST
#endif

/* By default don't care about exceptions. */
#ifndef FP_EX_INVALID
#define FP_EX_INVALID		0
#endif
#ifndef FP_EX_OVERFLOW
#define FP_EX_OVERFLOW		0
#endif
#ifndef FP_EX_UNDERFLOW
#define FP_EX_UNDERFLOW		0
#endif
#ifndef FP_EX_DIVZERO
#define FP_EX_DIVZERO		0
#endif
#ifndef FP_EX_INEXACT
#define FP_EX_INEXACT		0
#endif
#ifndef FP_EX_DENORM
#define FP_EX_DENORM		0
#endif

/* _FP_STRUCT_LAYOUT may be defined as an attribute to determine the
   struct layout variant used for structures where bit-fields are used
   to access specific parts of binary floating-point numbers.  This is
   required for systems where the default ABI uses struct layout with
   differences in how consecutive bit-fields are laid out from the
   default expected by soft-fp.  */
#ifndef _FP_STRUCT_LAYOUT
#define _FP_STRUCT_LAYOUT
#endif

#ifdef _FP_DECL_EX
#define FP_DECL_EX					\
  int _fex = 0;						\
  _FP_DECL_EX
#else
#define FP_DECL_EX int _fex = 0
#endif

#ifndef FP_INIT_ROUNDMODE
#define FP_INIT_ROUNDMODE do {} while (0)
#endif

#ifndef FP_HANDLE_EXCEPTIONS
#define FP_HANDLE_EXCEPTIONS do {} while (0)
#endif

#ifndef FP_INHIBIT_RESULTS
/* By default we write the results always.
 * sfp-machine may override this and e.g.
 * check if some exceptions are unmasked
 * and inhibit it in such a case.
 */
#define FP_INHIBIT_RESULTS 0
#endif

#define FP_SET_EXCEPTION(ex)				\
  _fex |= (ex)

#define FP_UNSET_EXCEPTION(ex)				\
  _fex &= ~(ex)

#define FP_CLEAR_EXCEPTIONS				\
  _fex = 0

#define FP_CUR_EXCEPTIONS				\
  (_fex)

#ifndef FP_TRAPPING_EXCEPTIONS
#define FP_TRAPPING_EXCEPTIONS 0
#endif

#define _FP_ROUND_NEAREST(wc, X)			\
do {							\
    if ((_FP_FRAC_LOW_##wc(X) & 15) != _FP_WORK_ROUND)	\
      _FP_FRAC_ADDI_##wc(X, _FP_WORK_ROUND);		\
} while (0)

#define _FP_ROUND_ZERO(wc, X)		(void)0

#define _FP_ROUND_PINF(wc, X)				\
do {							\
    if (!X##_s && (_FP_FRAC_LOW_##wc(X) & 7))		\
      _FP_FRAC_ADDI_##wc(X, _FP_WORK_LSB);		\
} while (0)

#define _FP_ROUND_MINF(wc, X)				\
do {							\
    if (X##_s && (_FP_FRAC_LOW_##wc(X) & 7))		\
      _FP_FRAC_ADDI_##wc(X, _FP_WORK_LSB);		\
} while (0)

#define _FP_ROUND(wc, X)			\
do {						\
	if (_FP_FRAC_LOW_##wc(X) & 7)		\
	  FP_SET_EXCEPTION(FP_EX_INEXACT);	\
	switch (FP_ROUNDMODE)			\
	{					\
	  case FP_RND_NEAREST:			\
	    _FP_ROUND_NEAREST(wc,X);		\
	    break;				\
	  case FP_RND_ZERO:			\
	    _FP_ROUND_ZERO(wc,X);		\
	    break;				\
	  case FP_RND_PINF:			\
	    _FP_ROUND_PINF(wc,X);		\
	    break;				\
	  case FP_RND_MINF:			\
	    _FP_ROUND_MINF(wc,X);		\
	    break;				\
	}					\
} while (0)

#define FP_CLS_NORMAL		0
#define FP_CLS_ZERO		1
#define FP_CLS_INF		2
#define FP_CLS_NAN		3

#define _FP_CLS_COMBINE(x,y)	(((x) << 2) | (y))

//#include "op-1.h"

#define _FP_FRAC_DECL_1(X)	_FP_W_TYPE X##_f
#define _FP_FRAC_COPY_1(D,S)	(D##_f = S##_f)
#define _FP_FRAC_SET_1(X,I)	(X##_f = I)
#define _FP_FRAC_HIGH_1(X)	(X##_f)
#define _FP_FRAC_LOW_1(X)	(X##_f)
#define _FP_FRAC_WORD_1(X,w)	(X##_f)

#define _FP_FRAC_ADDI_1(X,I)	(X##_f += I)
#define _FP_FRAC_SLL_1(X,N)			\
  do {						\
    if (__builtin_constant_p(N) && (N) == 1)	\
      X##_f += X##_f;				\
    else					\
      X##_f <<= (N);				\
  } while (0)
#define _FP_FRAC_SRL_1(X,N)	(X##_f >>= N)

/* Right shift with sticky-lsb.  */
#define _FP_FRAC_SRST_1(X,S,N,sz)	__FP_FRAC_SRST_1(X##_f, S, N, sz)
#define _FP_FRAC_SRS_1(X,N,sz)	__FP_FRAC_SRS_1(X##_f, N, sz)

#define __FP_FRAC_SRST_1(X,S,N,sz)			\
do {							\
  S = (__builtin_constant_p(N) && (N) == 1		\
       ? X & 1 : (X << (_FP_W_TYPE_SIZE - (N))) != 0);	\
  X = X >> (N);						\
} while (0)

#define __FP_FRAC_SRS_1(X,N,sz)						\
   (X = (X >> (N) | (__builtin_constant_p(N) && (N) == 1		\
		     ? X & 1 : (X << (_FP_W_TYPE_SIZE - (N))) != 0)))

#define _FP_FRAC_ADD_1(R,X,Y)	(R##_f = X##_f + Y##_f)
#define _FP_FRAC_SUB_1(R,X,Y)	(R##_f = X##_f - Y##_f)
#define _FP_FRAC_DEC_1(X,Y)	(X##_f -= Y##_f)
#define _FP_FRAC_CLZ_1(z, X)	__FP_CLZ(z, X##_f)

/* Predicates */
#define _FP_FRAC_NEGP_1(X)	((_FP_WS_TYPE)X##_f < 0)
#define _FP_FRAC_ZEROP_1(X)	(X##_f == 0)
#define _FP_FRAC_OVERP_1(fs,X)	(X##_f & _FP_OVERFLOW_##fs)
#define _FP_FRAC_CLEAR_OVERP_1(fs,X)	(X##_f &= ~_FP_OVERFLOW_##fs)
#define _FP_FRAC_EQ_1(X, Y)	(X##_f == Y##_f)
#define _FP_FRAC_GE_1(X, Y)	(X##_f >= Y##_f)
#define _FP_FRAC_GT_1(X, Y)	(X##_f > Y##_f)

#define _FP_ZEROFRAC_1		0
#define _FP_MINFRAC_1		1
#define _FP_MAXFRAC_1		(~(_FP_WS_TYPE)0)

/*
 * Unpack the raw bits of a native fp value.  Do not classify or
 * normalize the data.
 */

#define _FP_UNPACK_RAW_1(fs, X, val)				\
  do {								\
    union _FP_UNION_##fs _flo; _flo.flt = (val);		\
								\
    X##_f = _flo.bits.frac;					\
    X##_e = _flo.bits.exp;					\
    X##_s = _flo.bits.sign;					\
  } while (0)

#define _FP_UNPACK_RAW_1_P(fs, X, val)				\
  do {								\
    union _FP_UNION_##fs *_flo =				\
      (union _FP_UNION_##fs *)(val);				\
								\
    X##_f = _flo->bits.frac;					\
    X##_e = _flo->bits.exp;					\
    X##_s = _flo->bits.sign;					\
  } while (0)

/*
 * Repack the raw bits of a native fp value.
 */

#define _FP_PACK_RAW_1(fs, val, X)				\
  do {								\
    union _FP_UNION_##fs _flo;					\
								\
    _flo.bits.frac = X##_f;					\
    _flo.bits.exp  = X##_e;					\
    _flo.bits.sign = X##_s;					\
								\
    (val) = _flo.flt;						\
  } while (0)

#define _FP_PACK_RAW_1_P(fs, val, X)				\
  do {								\
    union _FP_UNION_##fs *_flo =				\
      (union _FP_UNION_##fs *)(val);				\
								\
    _flo->bits.frac = X##_f;					\
    _flo->bits.exp  = X##_e;					\
    _flo->bits.sign = X##_s;					\
  } while (0)


/*
 * Multiplication algorithms:
 */

/* Basic.  Assuming the host word size is >= 2*FRACBITS, we can do the
   multiplication immediately.  */

#define _FP_MUL_MEAT_1_imm(wfracbits, R, X, Y)				\
  do {									\
    R##_f = X##_f * Y##_f;						\
    /* Normalize since we know where the msb of the multiplicands	\
       were (bit B), we know that the msb of the of the product is	\
       at either 2B or 2B-1.  */					\
    _FP_FRAC_SRS_1(R, wfracbits-1, 2*wfracbits);			\
  } while (0)

/* Given a 1W * 1W => 2W primitive, do the extended multiplication.  */

#define _FP_MUL_MEAT_1_wide(wfracbits, R, X, Y, doit)			\
  do {									\
    _FP_W_TYPE _Z_f0, _Z_f1;						\
    doit(_Z_f1, _Z_f0, X##_f, Y##_f);					\
    /* Normalize since we know where the msb of the multiplicands	\
       were (bit B), we know that the msb of the of the product is	\
       at either 2B or 2B-1.  */					\
    _FP_FRAC_SRS_2(_Z, wfracbits-1, 2*wfracbits);			\
    R##_f = _Z_f0;							\
  } while (0)

/* Finally, a simple widening multiply algorithm.  What fun!  */

#define _FP_MUL_MEAT_1_hard(wfracbits, R, X, Y)				\
  do {									\
    _FP_W_TYPE _xh, _xl, _yh, _yl, _z_f0, _z_f1, _a_f0, _a_f1;		\
									\
    /* split the words in half */					\
    _xh = X##_f >> (_FP_W_TYPE_SIZE/2);					\
    _xl = X##_f & (((_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE/2)) - 1);		\
    _yh = Y##_f >> (_FP_W_TYPE_SIZE/2);					\
    _yl = Y##_f & (((_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE/2)) - 1);		\
									\
    /* multiply the pieces */						\
    _z_f0 = _xl * _yl;							\
    _a_f0 = _xh * _yl;							\
    _a_f1 = _xl * _yh;							\
    _z_f1 = _xh * _yh;							\
									\
    /* reassemble into two full words */				\
    if ((_a_f0 += _a_f1) < _a_f1)					\
      _z_f1 += (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE/2);			\
    _a_f1 = _a_f0 >> (_FP_W_TYPE_SIZE/2);				\
    _a_f0 = _a_f0 << (_FP_W_TYPE_SIZE/2);				\
    _FP_FRAC_ADD_2(_z, _z, _a);						\
									\
    /* normalize */							\
    _FP_FRAC_SRS_2(_z, wfracbits - 1, 2*wfracbits);			\
    R##_f = _z_f0;							\
  } while (0)


/*
 * Division algorithms:
 */

/* Basic.  Assuming the host word size is >= 2*FRACBITS, we can do the
   division immediately.  Give this macro either _FP_DIV_HELP_imm for
   C primitives or _FP_DIV_HELP_ldiv for the ISO function.  Which you
   choose will depend on what the compiler does with divrem4.  */

#define _FP_DIV_MEAT_1_imm(fs, R, X, Y, doit)		\
  do {							\
    _FP_W_TYPE _q, _r;					\
    X##_f <<= (X##_f < Y##_f				\
	       ? R##_e--, _FP_WFRACBITS_##fs		\
	       : _FP_WFRACBITS_##fs - 1);		\
    doit(_q, _r, X##_f, Y##_f);				\
    R##_f = _q | (_r != 0);				\
  } while (0)

/* GCC's longlong.h defines a 2W / 1W => (1W,1W) primitive udiv_qrnnd
   that may be useful in this situation.  This first is for a primitive
   that requires normalization, the second for one that does not.  Look
   for UDIV_NEEDS_NORMALIZATION to tell which your machine needs.  */

#define _FP_DIV_MEAT_1_udiv_norm(fs, R, X, Y)				\
  do {									\
    _FP_W_TYPE _nh, _nl, _q, _r, _y;					\
									\
    /* Normalize Y -- i.e. make the most significant bit set.  */	\
    _y = Y##_f << _FP_WFRACXBITS_##fs;					\
									\
    /* Shift X op correspondingly high, that is, up one full word.  */	\
    if (X##_f < Y##_f)							\
      {									\
	R##_e--;							\
	_nl = 0;							\
	_nh = X##_f;							\
      }									\
    else								\
      {									\
	_nl = X##_f << (_FP_W_TYPE_SIZE - 1);				\
	_nh = X##_f >> 1;						\
      }									\
    									\
    udiv_qrnnd(_q, _r, _nh, _nl, _y);					\
    R##_f = _q | (_r != 0);						\
  } while (0)

#define _FP_DIV_MEAT_1_udiv(fs, R, X, Y)		\
  do {							\
    _FP_W_TYPE _nh, _nl, _q, _r;			\
    if (X##_f < Y##_f)					\
      {							\
	R##_e--;					\
	_nl = X##_f << _FP_WFRACBITS_##fs;		\
	_nh = X##_f >> _FP_WFRACXBITS_##fs;		\
      }							\
    else						\
      {							\
	_nl = X##_f << (_FP_WFRACBITS_##fs - 1);	\
	_nh = X##_f >> (_FP_WFRACXBITS_##fs + 1);	\
      }							\
    udiv_qrnnd(_q, _r, _nh, _nl, Y##_f);		\
    R##_f = _q | (_r != 0);				\
  } while (0)
  
  
/*
 * Square root algorithms:
 * We have just one right now, maybe Newton approximation
 * should be added for those machines where division is fast.
 */
 
#define _FP_SQRT_MEAT_1(R, S, T, X, q)			\
  do {							\
    while (q != _FP_WORK_ROUND)				\
      {							\
        T##_f = S##_f + q;				\
        if (T##_f <= X##_f)				\
          {						\
            S##_f = T##_f + q;				\
            X##_f -= T##_f;				\
            R##_f += q;					\
          }						\
        _FP_FRAC_SLL_1(X, 1);				\
        q >>= 1;					\
      }							\
    if (X##_f)						\
      {							\
	if (S##_f < X##_f)				\
	  R##_f |= _FP_WORK_ROUND;			\
	R##_f |= _FP_WORK_STICKY;			\
      }							\
  } while (0)

/*
 * Assembly/disassembly for converting to/from integral types.  
 * No shifting or overflow handled here.
 */

#define _FP_FRAC_ASSEMBLE_1(r, X, rsize)	(r = X##_f)
#define _FP_FRAC_DISASSEMBLE_1(X, r, rsize)	(X##_f = r)


/*
 * Convert FP values between word sizes
 */

#define _FP_FRAC_COPY_1_1(D, S)		(D##_f = S##_f)


//#include "op-2.h"

#define _FP_FRAC_DECL_2(X)	_FP_W_TYPE X##_f0, X##_f1
#define _FP_FRAC_COPY_2(D,S)	(D##_f0 = S##_f0, D##_f1 = S##_f1)
#define _FP_FRAC_SET_2(X,I)	__FP_FRAC_SET_2(X, I)
#define _FP_FRAC_HIGH_2(X)	(X##_f1)
#define _FP_FRAC_LOW_2(X)	(X##_f0)
#define _FP_FRAC_WORD_2(X,w)	(X##_f##w)

#define _FP_FRAC_SLL_2(X,N)						    \
(void)(((N) < _FP_W_TYPE_SIZE)						    \
       ? ({								    \
	    if (__builtin_constant_p(N) && (N) == 1)			    \
	      {								    \
		X##_f1 = X##_f1 + X##_f1 + (((_FP_WS_TYPE)(X##_f0)) < 0);   \
		X##_f0 += X##_f0;					    \
	      }								    \
	    else							    \
	      {								    \
		X##_f1 = X##_f1 << (N) | X##_f0 >> (_FP_W_TYPE_SIZE - (N)); \
		X##_f0 <<= (N);						    \
	      }								    \
	    0;								    \
	  })								    \
       : ({								    \
	    X##_f1 = X##_f0 << ((N) - _FP_W_TYPE_SIZE);			    \
	    X##_f0 = 0;							    \
	  }))


#define _FP_FRAC_SRL_2(X,N)						\
(void)(((N) < _FP_W_TYPE_SIZE)						\
       ? ({								\
	    X##_f0 = X##_f0 >> (N) | X##_f1 << (_FP_W_TYPE_SIZE - (N));	\
	    X##_f1 >>= (N);						\
	  })								\
       : ({								\
	    X##_f0 = X##_f1 >> ((N) - _FP_W_TYPE_SIZE);			\
	    X##_f1 = 0;							\
	  }))

/* Right shift with sticky-lsb.  */
#define _FP_FRAC_SRST_2(X,S, N,sz)					  \
(void)(((N) < _FP_W_TYPE_SIZE)						  \
       ? ({								  \
	    S = (__builtin_constant_p(N) && (N) == 1			  \
		 ? X##_f0 & 1						  \
		 : (X##_f0 << (_FP_W_TYPE_SIZE - (N))) != 0);		  \
	    X##_f0 = (X##_f1 << (_FP_W_TYPE_SIZE - (N)) | X##_f0 >> (N)); \
	    X##_f1 >>= (N);						  \
	  })								  \
       : ({								  \
	    S = ((((N) == _FP_W_TYPE_SIZE				  \
		   ? 0							  \
		   : (X##_f1 << (2*_FP_W_TYPE_SIZE - (N))))		  \
		  | X##_f0) != 0);					  \
	    X##_f0 = (X##_f1 >> ((N) - _FP_W_TYPE_SIZE));		  \
	    X##_f1 = 0;							  \
	  }))

#define _FP_FRAC_SRS_2(X,N,sz)						  \
(void)(((N) < _FP_W_TYPE_SIZE)						  \
       ? ({								  \
	    X##_f0 = (X##_f1 << (_FP_W_TYPE_SIZE - (N)) | X##_f0 >> (N) | \
		      (__builtin_constant_p(N) && (N) == 1		  \
		       ? X##_f0 & 1					  \
		       : (X##_f0 << (_FP_W_TYPE_SIZE - (N))) != 0));	  \
	    X##_f1 >>= (N);						  \
	  })								  \
       : ({								  \
	    X##_f0 = (X##_f1 >> ((N) - _FP_W_TYPE_SIZE) |		  \
		      ((((N) == _FP_W_TYPE_SIZE				  \
			 ? 0						  \
			 : (X##_f1 << (2*_FP_W_TYPE_SIZE - (N))))	  \
			| X##_f0) != 0));				  \
	    X##_f1 = 0;							  \
	  }))

#define _FP_FRAC_ADDI_2(X,I)	\
  __FP_FRAC_ADDI_2(X##_f1, X##_f0, I)

#define _FP_FRAC_ADD_2(R,X,Y)	\
  __FP_FRAC_ADD_2(R##_f1, R##_f0, X##_f1, X##_f0, Y##_f1, Y##_f0)

#define _FP_FRAC_SUB_2(R,X,Y)	\
  __FP_FRAC_SUB_2(R##_f1, R##_f0, X##_f1, X##_f0, Y##_f1, Y##_f0)

#define _FP_FRAC_DEC_2(X,Y)	\
  __FP_FRAC_DEC_2(X##_f1, X##_f0, Y##_f1, Y##_f0)

#define _FP_FRAC_CLZ_2(R,X)	\
  do {				\
    if (X##_f1)			\
      __FP_CLZ(R,X##_f1);	\
    else 			\
    {				\
      __FP_CLZ(R,X##_f0);	\
      R += _FP_W_TYPE_SIZE;	\
    }				\
  } while(0)

/* Predicates */
#define _FP_FRAC_NEGP_2(X)	((_FP_WS_TYPE)X##_f1 < 0)
#define _FP_FRAC_ZEROP_2(X)	((X##_f1 | X##_f0) == 0)
#define _FP_FRAC_OVERP_2(fs,X)	(_FP_FRAC_HIGH_##fs(X) & _FP_OVERFLOW_##fs)
#define _FP_FRAC_CLEAR_OVERP_2(fs,X)	(_FP_FRAC_HIGH_##fs(X) &= ~_FP_OVERFLOW_##fs)
#define _FP_FRAC_EQ_2(X, Y)	(X##_f1 == Y##_f1 && X##_f0 == Y##_f0)
#define _FP_FRAC_GT_2(X, Y)	\
  (X##_f1 > Y##_f1 || (X##_f1 == Y##_f1 && X##_f0 > Y##_f0))
#define _FP_FRAC_GE_2(X, Y)	\
  (X##_f1 > Y##_f1 || (X##_f1 == Y##_f1 && X##_f0 >= Y##_f0))

#define _FP_ZEROFRAC_2		0, 0
#define _FP_MINFRAC_2		0, 1
#define _FP_MAXFRAC_2		(~(_FP_WS_TYPE)0), (~(_FP_WS_TYPE)0)

/*
 * Internals 
 */

#define __FP_FRAC_SET_2(X,I1,I0)	(X##_f0 = I0, X##_f1 = I1)

#define __FP_CLZ_2(R, xh, xl)	\
  do {				\
    if (xh)			\
      __FP_CLZ(R,xh);		\
    else 			\
    {				\
      __FP_CLZ(R,xl);		\
      R += _FP_W_TYPE_SIZE;	\
    }				\
  } while(0)

#if 0

#ifndef __FP_FRAC_ADDI_2
#define __FP_FRAC_ADDI_2(xh, xl, i)	\
  (xh += ((xl += i) < i))
#endif
#ifndef __FP_FRAC_ADD_2
#define __FP_FRAC_ADD_2(rh, rl, xh, xl, yh, yl)	\
  (rh = xh + yh + ((rl = xl + yl) < xl))
#endif
#ifndef __FP_FRAC_SUB_2
#define __FP_FRAC_SUB_2(rh, rl, xh, xl, yh, yl)	\
  (rh = xh - yh - ((rl = xl - yl) > xl))
#endif
#ifndef __FP_FRAC_DEC_2
#define __FP_FRAC_DEC_2(xh, xl, yh, yl)	\
  do {					\
    UWtype _t = xl;			\
    xh -= yh + ((xl -= yl) > _t);	\
  } while (0)
#endif

#else

#undef __FP_FRAC_ADDI_2
#define __FP_FRAC_ADDI_2(xh, xl, i)	add_ssaaaa(xh, xl, xh, xl, 0, i)
#undef __FP_FRAC_ADD_2
#define __FP_FRAC_ADD_2			add_ssaaaa
#undef __FP_FRAC_SUB_2
#define __FP_FRAC_SUB_2			sub_ddmmss
#undef __FP_FRAC_DEC_2
#define __FP_FRAC_DEC_2(xh, xl, yh, yl)	sub_ddmmss(xh, xl, xh, xl, yh, yl)

#endif

/*
 * Unpack the raw bits of a native fp value.  Do not classify or
 * normalize the data.
 */

#define _FP_UNPACK_RAW_2(fs, X, val)			\
  do {							\
    union _FP_UNION_##fs _flo; _flo.flt = (val);	\
							\
    X##_f0 = _flo.bits.frac0;				\
    X##_f1 = _flo.bits.frac1;				\
    X##_e  = _flo.bits.exp;				\
    X##_s  = _flo.bits.sign;				\
  } while (0)

#define _FP_UNPACK_RAW_2_P(fs, X, val)			\
  do {							\
    union _FP_UNION_##fs *_flo =			\
      (union _FP_UNION_##fs *)(val);			\
							\
    X##_f0 = _flo->bits.frac0;				\
    X##_f1 = _flo->bits.frac1;				\
    X##_e  = _flo->bits.exp;				\
    X##_s  = _flo->bits.sign;				\
  } while (0)


/*
 * Repack the raw bits of a native fp value.
 */

#define _FP_PACK_RAW_2(fs, val, X)			\
  do {							\
    union _FP_UNION_##fs _flo;				\
							\
    _flo.bits.frac0 = X##_f0;				\
    _flo.bits.frac1 = X##_f1;				\
    _flo.bits.exp   = X##_e;				\
    _flo.bits.sign  = X##_s;				\
							\
    (val) = _flo.flt;					\
  } while (0)

#define _FP_PACK_RAW_2_P(fs, val, X)			\
  do {							\
    union _FP_UNION_##fs *_flo =			\
      (union _FP_UNION_##fs *)(val);			\
							\
    _flo->bits.frac0 = X##_f0;				\
    _flo->bits.frac1 = X##_f1;				\
    _flo->bits.exp   = X##_e;				\
    _flo->bits.sign  = X##_s;				\
  } while (0)


/*
 * Multiplication algorithms:
 */

/* Given a 1W * 1W => 2W primitive, do the extended multiplication.  */

#define _FP_MUL_MEAT_2_wide(wfracbits, R, X, Y, doit)			\
  do {									\
    _FP_FRAC_DECL_4(_z); _FP_FRAC_DECL_2(_b); _FP_FRAC_DECL_2(_c);	\
									\
    doit(_FP_FRAC_WORD_4(_z,1), _FP_FRAC_WORD_4(_z,0), X##_f0, Y##_f0);	\
    doit(_b_f1, _b_f0, X##_f0, Y##_f1);					\
    doit(_c_f1, _c_f0, X##_f1, Y##_f0);					\
    doit(_FP_FRAC_WORD_4(_z,3), _FP_FRAC_WORD_4(_z,2), X##_f1, Y##_f1);	\
									\
    __FP_FRAC_ADD_3(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2),	\
		    _FP_FRAC_WORD_4(_z,1), 0, _b_f1, _b_f0,		\
		    _FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2),	\
		    _FP_FRAC_WORD_4(_z,1));				\
    __FP_FRAC_ADD_3(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2),	\
		    _FP_FRAC_WORD_4(_z,1), 0, _c_f1, _c_f0,		\
		    _FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2),	\
		    _FP_FRAC_WORD_4(_z,1));				\
									\
    /* Normalize since we know where the msb of the multiplicands	\
       were (bit B), we know that the msb of the of the product is	\
       at either 2B or 2B-1.  */					\
    _FP_FRAC_SRS_4(_z, wfracbits-1, 2*wfracbits);			\
    R##_f0 = _FP_FRAC_WORD_4(_z,0);					\
    R##_f1 = _FP_FRAC_WORD_4(_z,1);					\
  } while (0)

/* Given a 1W * 1W => 2W primitive, do the extended multiplication.
   Do only 3 multiplications instead of four. This one is for machines
   where multiplication is much more expensive than subtraction.  */

#define _FP_MUL_MEAT_2_wide_3mul(wfracbits, R, X, Y, doit)		\
  do {									\
    _FP_FRAC_DECL_4(_z); _FP_FRAC_DECL_2(_b); _FP_FRAC_DECL_2(_c);	\
    _FP_W_TYPE _d;							\
    int _c1, _c2;							\
									\
    _b_f0 = X##_f0 + X##_f1;						\
    _c1 = _b_f0 < X##_f0;						\
    _b_f1 = Y##_f0 + Y##_f1;						\
    _c2 = _b_f1 < Y##_f0;						\
    doit(_d, _FP_FRAC_WORD_4(_z,0), X##_f0, Y##_f0);			\
    doit(_FP_FRAC_WORD_4(_z,2), _FP_FRAC_WORD_4(_z,1), _b_f0, _b_f1);	\
    doit(_c_f1, _c_f0, X##_f1, Y##_f1);					\
									\
    _b_f0 &= -_c2;							\
    _b_f1 &= -_c1;							\
    __FP_FRAC_ADD_3(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2),	\
		    _FP_FRAC_WORD_4(_z,1), (_c1 & _c2), 0, _d,		\
		    0, _FP_FRAC_WORD_4(_z,2), _FP_FRAC_WORD_4(_z,1));	\
    __FP_FRAC_ADDI_2(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2),	\
		     _b_f0);						\
    __FP_FRAC_ADDI_2(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2),	\
		     _b_f1);						\
    __FP_FRAC_DEC_3(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2),	\
		    _FP_FRAC_WORD_4(_z,1),				\
		    0, _d, _FP_FRAC_WORD_4(_z,0));			\
    __FP_FRAC_DEC_3(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2),	\
		    _FP_FRAC_WORD_4(_z,1), 0, _c_f1, _c_f0);		\
    __FP_FRAC_ADD_2(_FP_FRAC_WORD_4(_z,3), _FP_FRAC_WORD_4(_z,2),	\
		    _c_f1, _c_f0,					\
		    _FP_FRAC_WORD_4(_z,3), _FP_FRAC_WORD_4(_z,2));	\
									\
    /* Normalize since we know where the msb of the multiplicands	\
       were (bit B), we know that the msb of the of the product is	\
       at either 2B or 2B-1.  */					\
    _FP_FRAC_SRS_4(_z, wfracbits-1, 2*wfracbits);			\
    R##_f0 = _FP_FRAC_WORD_4(_z,0);					\
    R##_f1 = _FP_FRAC_WORD_4(_z,1);					\
  } while (0)

#define _FP_MUL_MEAT_2_gmp(wfracbits, R, X, Y)				\
  do {									\
    _FP_FRAC_DECL_4(_z);						\
    _FP_W_TYPE _x[2], _y[2];						\
    _x[0] = X##_f0; _x[1] = X##_f1;					\
    _y[0] = Y##_f0; _y[1] = Y##_f1;					\
									\
    mpn_mul_n(_z_f, _x, _y, 2);						\
									\
    /* Normalize since we know where the msb of the multiplicands	\
       were (bit B), we know that the msb of the of the product is	\
       at either 2B or 2B-1.  */					\
    _FP_FRAC_SRS_4(_z, wfracbits-1, 2*wfracbits);			\
    R##_f0 = _z_f[0];							\
    R##_f1 = _z_f[1];							\
  } while (0)

/* Do at most 120x120=240 bits multiplication using double floating
   point multiplication.  This is useful if floating point
   multiplication has much bigger throughput than integer multiply.
   It is supposed to work for _FP_W_TYPE_SIZE 64 and wfracbits
   between 106 and 120 only.  
   Caller guarantees that X and Y has (1LLL << (wfracbits - 1)) set.
   SETFETZ is a macro which will disable all FPU exceptions and set rounding
   towards zero,  RESETFE should optionally reset it back.  */

#define _FP_MUL_MEAT_2_120_240_double(wfracbits, R, X, Y, setfetz, resetfe)	\
  do {										\
    static const double _const[] = {						\
      /* 2^-24 */ 5.9604644775390625e-08,					\
      /* 2^-48 */ 3.5527136788005009e-15,					\
      /* 2^-72 */ 2.1175823681357508e-22,					\
      /* 2^-96 */ 1.2621774483536189e-29,					\
      /* 2^28 */ 2.68435456e+08,						\
      /* 2^4 */ 1.600000e+01,							\
      /* 2^-20 */ 9.5367431640625e-07,						\
      /* 2^-44 */ 5.6843418860808015e-14,					\
      /* 2^-68 */ 3.3881317890172014e-21,					\
      /* 2^-92 */ 2.0194839173657902e-28,					\
      /* 2^-116 */ 1.2037062152420224e-35};					\
    double _a240, _b240, _c240, _d240, _e240, _f240, 				\
	   _g240, _h240, _i240, _j240, _k240;					\
    union { double d; UDItype i; } _l240, _m240, _n240, _o240,			\
				   _p240, _q240, _r240, _s240;			\
    UDItype _t240, _u240, _v240, _w240, _x240, _y240 = 0;			\
										\
    if (wfracbits < 106 || wfracbits > 120)					\
      abort();									\
										\
    setfetz;									\
										\
    _e240 = (double)(long)(X##_f0 & 0xffffff);					\
    _j240 = (double)(long)(Y##_f0 & 0xffffff);					\
    _d240 = (double)(long)((X##_f0 >> 24) & 0xffffff);				\
    _i240 = (double)(long)((Y##_f0 >> 24) & 0xffffff);				\
    _c240 = (double)(long)(((X##_f1 << 16) & 0xffffff) | (X##_f0 >> 48));	\
    _h240 = (double)(long)(((Y##_f1 << 16) & 0xffffff) | (Y##_f0 >> 48));	\
    _b240 = (double)(long)((X##_f1 >> 8) & 0xffffff);				\
    _g240 = (double)(long)((Y##_f1 >> 8) & 0xffffff);				\
    _a240 = (double)(long)(X##_f1 >> 32);					\
    _f240 = (double)(long)(Y##_f1 >> 32);					\
    _e240 *= _const[3];								\
    _j240 *= _const[3];								\
    _d240 *= _const[2];								\
    _i240 *= _const[2];								\
    _c240 *= _const[1];								\
    _h240 *= _const[1];								\
    _b240 *= _const[0];								\
    _g240 *= _const[0];								\
    _s240.d =							      _e240*_j240;\
    _r240.d =						_d240*_j240 + _e240*_i240;\
    _q240.d =				  _c240*_j240 + _d240*_i240 + _e240*_h240;\
    _p240.d =		    _b240*_j240 + _c240*_i240 + _d240*_h240 + _e240*_g240;\
    _o240.d = _a240*_j240 + _b240*_i240 + _c240*_h240 + _d240*_g240 + _e240*_f240;\
    _n240.d = _a240*_i240 + _b240*_h240 + _c240*_g240 + _d240*_f240;		\
    _m240.d = _a240*_h240 + _b240*_g240 + _c240*_f240;				\
    _l240.d = _a240*_g240 + _b240*_f240;					\
    _k240 =   _a240*_f240;							\
    _r240.d += _s240.d;								\
    _q240.d += _r240.d;								\
    _p240.d += _q240.d;								\
    _o240.d += _p240.d;								\
    _n240.d += _o240.d;								\
    _m240.d += _n240.d;								\
    _l240.d += _m240.d;								\
    _k240 += _l240.d;								\
    _s240.d -= ((_const[10]+_s240.d)-_const[10]);				\
    _r240.d -= ((_const[9]+_r240.d)-_const[9]);					\
    _q240.d -= ((_const[8]+_q240.d)-_const[8]);					\
    _p240.d -= ((_const[7]+_p240.d)-_const[7]);					\
    _o240.d += _const[7];							\
    _n240.d += _const[6];							\
    _m240.d += _const[5];							\
    _l240.d += _const[4];							\
    if (_s240.d != 0.0) _y240 = 1;						\
    if (_r240.d != 0.0) _y240 = 1;						\
    if (_q240.d != 0.0) _y240 = 1;						\
    if (_p240.d != 0.0) _y240 = 1;						\
    _t240 = (DItype)_k240;							\
    _u240 = _l240.i;								\
    _v240 = _m240.i;								\
    _w240 = _n240.i;								\
    _x240 = _o240.i;								\
    R##_f1 = (_t240 << (128 - (wfracbits - 1)))					\
	     | ((_u240 & 0xffffff) >> ((wfracbits - 1) - 104));			\
    R##_f0 = ((_u240 & 0xffffff) << (168 - (wfracbits - 1)))			\
    	     | ((_v240 & 0xffffff) << (144 - (wfracbits - 1)))			\
    	     | ((_w240 & 0xffffff) << (120 - (wfracbits - 1)))			\
    	     | ((_x240 & 0xffffff) >> ((wfracbits - 1) - 96))			\
    	     | _y240;								\
    resetfe;									\
  } while (0)

/*
 * Division algorithms:
 */

#define _FP_DIV_MEAT_2_udiv(fs, R, X, Y)				\
  do {									\
    _FP_W_TYPE _n_f2, _n_f1, _n_f0, _r_f1, _r_f0, _m_f1, _m_f0;		\
    if (_FP_FRAC_GT_2(X, Y))						\
      {									\
	_n_f2 = X##_f1 >> 1;						\
	_n_f1 = X##_f1 << (_FP_W_TYPE_SIZE - 1) | X##_f0 >> 1;		\
	_n_f0 = X##_f0 << (_FP_W_TYPE_SIZE - 1);			\
      }									\
    else								\
      {									\
	R##_e--;							\
	_n_f2 = X##_f1;							\
	_n_f1 = X##_f0;							\
	_n_f0 = 0;							\
      }									\
									\
    /* Normalize, i.e. make the most significant bit of the 		\
       denominator set. */						\
    _FP_FRAC_SLL_2(Y, _FP_WFRACXBITS_##fs);				\
									\
    udiv_qrnnd(R##_f1, _r_f1, _n_f2, _n_f1, Y##_f1);			\
    umul_ppmm(_m_f1, _m_f0, R##_f1, Y##_f0);				\
    _r_f0 = _n_f0;							\
    if (_FP_FRAC_GT_2(_m, _r))						\
      {									\
	R##_f1--;							\
	_FP_FRAC_ADD_2(_r, Y, _r);					\
	if (_FP_FRAC_GE_2(_r, Y) && _FP_FRAC_GT_2(_m, _r))		\
	  {								\
	    R##_f1--;							\
	    _FP_FRAC_ADD_2(_r, Y, _r);					\
	  }								\
      }									\
    _FP_FRAC_DEC_2(_r, _m);						\
									\
    if (_r_f1 == Y##_f1)						\
      {									\
	/* This is a special case, not an optimization			\
	   (_r/Y##_f1 would not fit into UWtype).			\
	   As _r is guaranteed to be < Y,  R##_f0 can be either		\
	   (UWtype)-1 or (UWtype)-2.  But as we know what kind		\
	   of bits it is (sticky, guard, round),  we don't care.	\
	   We also don't care what the reminder is,  because the	\
	   guard bit will be set anyway.  -jj */			\
	R##_f0 = -1;							\
      }									\
    else								\
      {									\
	udiv_qrnnd(R##_f0, _r_f1, _r_f1, _r_f0, Y##_f1);		\
	umul_ppmm(_m_f1, _m_f0, R##_f0, Y##_f0);			\
	_r_f0 = 0;							\
	if (_FP_FRAC_GT_2(_m, _r))					\
	  {								\
	    R##_f0--;							\
	    _FP_FRAC_ADD_2(_r, Y, _r);					\
	    if (_FP_FRAC_GE_2(_r, Y) && _FP_FRAC_GT_2(_m, _r))		\
	      {								\
		R##_f0--;						\
		_FP_FRAC_ADD_2(_r, Y, _r);				\
	      }								\
	  }								\
	if (!_FP_FRAC_EQ_2(_r, _m))					\
	  R##_f0 |= _FP_WORK_STICKY;					\
      }									\
  } while (0)


#define _FP_DIV_MEAT_2_gmp(fs, R, X, Y)					\
  do {									\
    _FP_W_TYPE _x[4], _y[2], _z[4];					\
    _y[0] = Y##_f0; _y[1] = Y##_f1;					\
    _x[0] = _x[3] = 0;							\
    if (_FP_FRAC_GT_2(X, Y))						\
      {									\
	R##_e++;							\
	_x[1] = (X##_f0 << (_FP_WFRACBITS_##fs-1 - _FP_W_TYPE_SIZE) |	\
		 X##_f1 >> (_FP_W_TYPE_SIZE -				\
			    (_FP_WFRACBITS_##fs-1 - _FP_W_TYPE_SIZE)));	\
	_x[2] = X##_f1 << (_FP_WFRACBITS_##fs-1 - _FP_W_TYPE_SIZE);	\
      }									\
    else								\
      {									\
	_x[1] = (X##_f0 << (_FP_WFRACBITS_##fs - _FP_W_TYPE_SIZE) |	\
		 X##_f1 >> (_FP_W_TYPE_SIZE -				\
			    (_FP_WFRACBITS_##fs - _FP_W_TYPE_SIZE)));	\
	_x[2] = X##_f1 << (_FP_WFRACBITS_##fs - _FP_W_TYPE_SIZE);	\
      }									\
									\
    (void) mpn_divrem (_z, 0, _x, 4, _y, 2);				\
    R##_f1 = _z[1];							\
    R##_f0 = _z[0] | ((_x[0] | _x[1]) != 0);				\
  } while (0)


/*
 * Square root algorithms:
 * We have just one right now, maybe Newton approximation
 * should be added for those machines where division is fast.
 */
 
#define _FP_SQRT_MEAT_2(R, S, T, X, q)			\
  do {							\
    while (q)						\
      {							\
	T##_f1 = S##_f1 + q;				\
	if (T##_f1 <= X##_f1)				\
	  {						\
	    S##_f1 = T##_f1 + q;			\
	    X##_f1 -= T##_f1;				\
	    R##_f1 += q;				\
	  }						\
	_FP_FRAC_SLL_2(X, 1);				\
	q >>= 1;					\
      }							\
    q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1);		\
    while (q != _FP_WORK_ROUND)				\
      {							\
	T##_f0 = S##_f0 + q;				\
	T##_f1 = S##_f1;				\
	if (T##_f1 < X##_f1 || 				\
	    (T##_f1 == X##_f1 && T##_f0 <= X##_f0))	\
	  {						\
	    S##_f0 = T##_f0 + q;			\
	    S##_f1 += (T##_f0 > S##_f0);		\
	    _FP_FRAC_DEC_2(X, T);			\
	    R##_f0 += q;				\
	  }						\
	_FP_FRAC_SLL_2(X, 1);				\
	q >>= 1;					\
      }							\
    if (X##_f0 | X##_f1)				\
      {							\
	if (S##_f1 < X##_f1 || 				\
	    (S##_f1 == X##_f1 && S##_f0 < X##_f0))	\
	  R##_f0 |= _FP_WORK_ROUND;			\
	R##_f0 |= _FP_WORK_STICKY;			\
      }							\
  } while (0)


/*
 * Assembly/disassembly for converting to/from integral types.  
 * No shifting or overflow handled here.
 */

#define _FP_FRAC_ASSEMBLE_2(r, X, rsize)	\
(void)((rsize <= _FP_W_TYPE_SIZE)		\
       ? ({ r = X##_f0; })			\
       : ({					\
	    r = X##_f1;				\
	    r <<= _FP_W_TYPE_SIZE;		\
	    r += X##_f0;			\
	  }))

#define _FP_FRAC_DISASSEMBLE_2(X, r, rsize)				\
  do {									\
    X##_f0 = r;								\
    X##_f1 = (rsize <= _FP_W_TYPE_SIZE ? 0 : r >> _FP_W_TYPE_SIZE);	\
  } while (0)

/*
 * Convert FP values between word sizes
 */

#define _FP_FRAC_COPY_1_2(D, S)		(D##_f = S##_f0)

#define _FP_FRAC_COPY_2_1(D, S)		((D##_f0 = S##_f), (D##_f1 = 0))

#define _FP_FRAC_COPY_2_2(D,S)		_FP_FRAC_COPY_2(D,S)


//#include "op-4.h"

#define _FP_FRAC_DECL_4(X)	_FP_W_TYPE X##_f[4]
#define _FP_FRAC_COPY_4(D,S)			\
  (D##_f[0] = S##_f[0], D##_f[1] = S##_f[1],	\
   D##_f[2] = S##_f[2], D##_f[3] = S##_f[3])
#define _FP_FRAC_SET_4(X,I)	__FP_FRAC_SET_4(X, I)
#define _FP_FRAC_HIGH_4(X)	(X##_f[3])
#define _FP_FRAC_LOW_4(X)	(X##_f[0])
#define _FP_FRAC_WORD_4(X,w)	(X##_f[w])

#define _FP_FRAC_SLL_4(X,N)						\
  do {									\
    _FP_I_TYPE _up, _down, _skip, _i;					\
    _skip = (N) / _FP_W_TYPE_SIZE;					\
    _up = (N) % _FP_W_TYPE_SIZE;					\
    _down = _FP_W_TYPE_SIZE - _up;					\
    if (!_up)								\
      for (_i = 3; _i >= _skip; --_i)					\
	X##_f[_i] = X##_f[_i-_skip];					\
    else								\
      {									\
	for (_i = 3; _i > _skip; --_i)					\
	  X##_f[_i] = X##_f[_i-_skip] << _up				\
		      | X##_f[_i-_skip-1] >> _down;			\
	X##_f[_i--] = X##_f[0] << _up; 					\
      }									\
    for (; _i >= 0; --_i)						\
      X##_f[_i] = 0;							\
  } while (0)

/* This one was broken too */
#define _FP_FRAC_SRL_4(X,N)						\
  do {									\
    _FP_I_TYPE _up, _down, _skip, _i;					\
    _skip = (N) / _FP_W_TYPE_SIZE;					\
    _down = (N) % _FP_W_TYPE_SIZE;					\
    _up = _FP_W_TYPE_SIZE - _down;					\
    if (!_down)								\
      for (_i = 0; _i <= 3-_skip; ++_i)					\
	X##_f[_i] = X##_f[_i+_skip];					\
    else								\
      {									\
	for (_i = 0; _i < 3-_skip; ++_i)				\
	  X##_f[_i] = X##_f[_i+_skip] >> _down				\
		      | X##_f[_i+_skip+1] << _up;			\
	X##_f[_i++] = X##_f[3] >> _down;				\
      }									\
    for (; _i < 4; ++_i)						\
      X##_f[_i] = 0;							\
  } while (0)


/* Right shift with sticky-lsb. 
 * What this actually means is that we do a standard right-shift,
 * but that if any of the bits that fall off the right hand side
 * were one then we always set the LSbit.
 */
#define _FP_FRAC_SRST_4(X,S,N,size)			\
  do {							\
    _FP_I_TYPE _up, _down, _skip, _i;			\
    _FP_W_TYPE _s;					\
    _skip = (N) / _FP_W_TYPE_SIZE;			\
    _down = (N) % _FP_W_TYPE_SIZE;			\
    _up = _FP_W_TYPE_SIZE - _down;			\
    for (_s = _i = 0; _i < _skip; ++_i)			\
      _s |= X##_f[_i];					\
    if (!_down)						\
      for (_i = 0; _i <= 3-_skip; ++_i)			\
	X##_f[_i] = X##_f[_i+_skip];			\
    else						\
      {							\
	_s |= X##_f[_i] << _up;				\
	for (_i = 0; _i < 3-_skip; ++_i)		\
	  X##_f[_i] = X##_f[_i+_skip] >> _down		\
		      | X##_f[_i+_skip+1] << _up;	\
	X##_f[_i++] = X##_f[3] >> _down;		\
      }							\
    for (; _i < 4; ++_i)				\
      X##_f[_i] = 0;					\
    S = (_s != 0);					\
  } while (0)

#define _FP_FRAC_SRS_4(X,N,size)		\
  do {						\
    int _sticky;				\
    _FP_FRAC_SRST_4(X, _sticky, N, size);	\
    X##_f[0] |= _sticky;			\
  } while (0)

#define _FP_FRAC_ADD_4(R,X,Y)						\
  __FP_FRAC_ADD_4(R##_f[3], R##_f[2], R##_f[1], R##_f[0],		\
		  X##_f[3], X##_f[2], X##_f[1], X##_f[0],		\
		  Y##_f[3], Y##_f[2], Y##_f[1], Y##_f[0])

#define _FP_FRAC_SUB_4(R,X,Y)						\
  __FP_FRAC_SUB_4(R##_f[3], R##_f[2], R##_f[1], R##_f[0],		\
		  X##_f[3], X##_f[2], X##_f[1], X##_f[0],		\
		  Y##_f[3], Y##_f[2], Y##_f[1], Y##_f[0])

#define _FP_FRAC_DEC_4(X,Y)						\
  __FP_FRAC_DEC_4(X##_f[3], X##_f[2], X##_f[1], X##_f[0],		\
		  Y##_f[3], Y##_f[2], Y##_f[1], Y##_f[0])

#define _FP_FRAC_ADDI_4(X,I)						\
  __FP_FRAC_ADDI_4(X##_f[3], X##_f[2], X##_f[1], X##_f[0], I)

#define _FP_ZEROFRAC_4  0,0,0,0
#define _FP_MINFRAC_4   0,0,0,1
#define _FP_MAXFRAC_4	(~(_FP_WS_TYPE)0), (~(_FP_WS_TYPE)0), (~(_FP_WS_TYPE)0), (~(_FP_WS_TYPE)0)

#define _FP_FRAC_ZEROP_4(X)     ((X##_f[0] | X##_f[1] | X##_f[2] | X##_f[3]) == 0)
#define _FP_FRAC_NEGP_4(X)      ((_FP_WS_TYPE)X##_f[3] < 0)
#define _FP_FRAC_OVERP_4(fs,X)  (_FP_FRAC_HIGH_##fs(X) & _FP_OVERFLOW_##fs)
#define _FP_FRAC_CLEAR_OVERP_4(fs,X)  (_FP_FRAC_HIGH_##fs(X) &= ~_FP_OVERFLOW_##fs)

#define _FP_FRAC_EQ_4(X,Y)				\
 (X##_f[0] == Y##_f[0] && X##_f[1] == Y##_f[1]		\
  && X##_f[2] == Y##_f[2] && X##_f[3] == Y##_f[3])

#define _FP_FRAC_GT_4(X,Y)				\
 (X##_f[3] > Y##_f[3] ||				\
  (X##_f[3] == Y##_f[3] && (X##_f[2] > Y##_f[2] ||	\
   (X##_f[2] == Y##_f[2] && (X##_f[1] > Y##_f[1] ||	\
    (X##_f[1] == Y##_f[1] && X##_f[0] > Y##_f[0])	\
   ))							\
  ))							\
 )

#define _FP_FRAC_GE_4(X,Y)				\
 (X##_f[3] > Y##_f[3] ||				\
  (X##_f[3] == Y##_f[3] && (X##_f[2] > Y##_f[2] ||	\
   (X##_f[2] == Y##_f[2] && (X##_f[1] > Y##_f[1] ||	\
    (X##_f[1] == Y##_f[1] && X##_f[0] >= Y##_f[0])	\
   ))							\
  ))							\
 )


#define _FP_FRAC_CLZ_4(R,X)		\
  do {					\
    if (X##_f[3])			\
    {					\
	__FP_CLZ(R,X##_f[3]);		\
    }					\
    else if (X##_f[2])			\
    {					\
	__FP_CLZ(R,X##_f[2]);		\
	R += _FP_W_TYPE_SIZE;		\
    }					\
    else if (X##_f[1])			\
    {					\
	__FP_CLZ(R,X##_f[1]);		\
	R += _FP_W_TYPE_SIZE*2;		\
    }					\
    else				\
    {					\
	__FP_CLZ(R,X##_f[0]);		\
	R += _FP_W_TYPE_SIZE*3;		\
    }					\
  } while(0)


#define _FP_UNPACK_RAW_4(fs, X, val)				\
  do {								\
    union _FP_UNION_##fs _flo; _flo.flt = (val);		\
    X##_f[0] = _flo.bits.frac0;					\
    X##_f[1] = _flo.bits.frac1;					\
    X##_f[2] = _flo.bits.frac2;					\
    X##_f[3] = _flo.bits.frac3;					\
    X##_e  = _flo.bits.exp;					\
    X##_s  = _flo.bits.sign;					\
  } while (0)

#define _FP_UNPACK_RAW_4_P(fs, X, val)				\
  do {								\
    union _FP_UNION_##fs *_flo =				\
      (union _FP_UNION_##fs *)(val);				\
								\
    X##_f[0] = _flo->bits.frac0;				\
    X##_f[1] = _flo->bits.frac1;				\
    X##_f[2] = _flo->bits.frac2;				\
    X##_f[3] = _flo->bits.frac3;				\
    X##_e  = _flo->bits.exp;					\
    X##_s  = _flo->bits.sign;					\
  } while (0)

#define _FP_PACK_RAW_4(fs, val, X)				\
  do {								\
    union _FP_UNION_##fs _flo;					\
    _flo.bits.frac0 = X##_f[0];					\
    _flo.bits.frac1 = X##_f[1];					\
    _flo.bits.frac2 = X##_f[2];					\
    _flo.bits.frac3 = X##_f[3];					\
    _flo.bits.exp   = X##_e;					\
    _flo.bits.sign  = X##_s;					\
    (val) = _flo.flt;				   		\
  } while (0)

#define _FP_PACK_RAW_4_P(fs, val, X)				\
  do {								\
    union _FP_UNION_##fs *_flo =				\
      (union _FP_UNION_##fs *)(val);				\
								\
    _flo->bits.frac0 = X##_f[0];				\
    _flo->bits.frac1 = X##_f[1];				\
    _flo->bits.frac2 = X##_f[2];				\
    _flo->bits.frac3 = X##_f[3];				\
    _flo->bits.exp   = X##_e;					\
    _flo->bits.sign  = X##_s;					\
  } while (0)

/*
 * Multiplication algorithms:
 */

/* Given a 1W * 1W => 2W primitive, do the extended multiplication.  */

#define _FP_MUL_MEAT_4_wide(wfracbits, R, X, Y, doit)			    \
  do {									    \
    _FP_FRAC_DECL_8(_z); _FP_FRAC_DECL_2(_b); _FP_FRAC_DECL_2(_c);	    \
    _FP_FRAC_DECL_2(_d); _FP_FRAC_DECL_2(_e); _FP_FRAC_DECL_2(_f);	    \
									    \
    doit(_FP_FRAC_WORD_8(_z,1), _FP_FRAC_WORD_8(_z,0), X##_f[0], Y##_f[0]); \
    doit(_b_f1, _b_f0, X##_f[0], Y##_f[1]);				    \
    doit(_c_f1, _c_f0, X##_f[1], Y##_f[0]);				    \
    doit(_d_f1, _d_f0, X##_f[1], Y##_f[1]);				    \
    doit(_e_f1, _e_f0, X##_f[0], Y##_f[2]);				    \
    doit(_f_f1, _f_f0, X##_f[2], Y##_f[0]);				    \
    __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,3),_FP_FRAC_WORD_8(_z,2),	    \
		    _FP_FRAC_WORD_8(_z,1), 0,_b_f1,_b_f0,		    \
		    0,0,_FP_FRAC_WORD_8(_z,1));				    \
    __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,3),_FP_FRAC_WORD_8(_z,2),	    \
		    _FP_FRAC_WORD_8(_z,1), 0,_c_f1,_c_f0,		    \
		    _FP_FRAC_WORD_8(_z,3),_FP_FRAC_WORD_8(_z,2),	    \
		    _FP_FRAC_WORD_8(_z,1));				    \
    __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,4),_FP_FRAC_WORD_8(_z,3),	    \
		    _FP_FRAC_WORD_8(_z,2), 0,_d_f1,_d_f0,		    \
		    0,_FP_FRAC_WORD_8(_z,3),_FP_FRAC_WORD_8(_z,2));	    \
    __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,4),_FP_FRAC_WORD_8(_z,3),	    \
		    _FP_FRAC_WORD_8(_z,2), 0,_e_f1,_e_f0,		    \
		    _FP_FRAC_WORD_8(_z,4),_FP_FRAC_WORD_8(_z,3),	    \
		    _FP_FRAC_WORD_8(_z,2));				    \
    __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,4),_FP_FRAC_WORD_8(_z,3),	    \
		    _FP_FRAC_WORD_8(_z,2), 0,_f_f1,_f_f0,		    \
		    _FP_FRAC_WORD_8(_z,4),_FP_FRAC_WORD_8(_z,3),	    \
		    _FP_FRAC_WORD_8(_z,2));				    \
    doit(_b_f1, _b_f0, X##_f[0], Y##_f[3]);				    \
    doit(_c_f1, _c_f0, X##_f[3], Y##_f[0]);				    \
    doit(_d_f1, _d_f0, X##_f[1], Y##_f[2]);				    \
    doit(_e_f1, _e_f0, X##_f[2], Y##_f[1]);				    \
    __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4),	    \
		    _FP_FRAC_WORD_8(_z,3), 0,_b_f1,_b_f0,		    \
		    0,_FP_FRAC_WORD_8(_z,4),_FP_FRAC_WORD_8(_z,3));	    \
    __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4),	    \
		    _FP_FRAC_WORD_8(_z,3), 0,_c_f1,_c_f0,		    \
		    _FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4),	    \
		    _FP_FRAC_WORD_8(_z,3));				    \
    __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4),	    \
		    _FP_FRAC_WORD_8(_z,3), 0,_d_f1,_d_f0,		    \
		    _FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4),	    \
		    _FP_FRAC_WORD_8(_z,3));				    \
    __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4),	    \
		    _FP_FRAC_WORD_8(_z,3), 0,_e_f1,_e_f0,		    \
		    _FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4),	    \
		    _FP_FRAC_WORD_8(_z,3));				    \
    doit(_b_f1, _b_f0, X##_f[2], Y##_f[2]);				    \
    doit(_c_f1, _c_f0, X##_f[1], Y##_f[3]);				    \
    doit(_d_f1, _d_f0, X##_f[3], Y##_f[1]);				    \
    doit(_e_f1, _e_f0, X##_f[2], Y##_f[3]);				    \
    doit(_f_f1, _f_f0, X##_f[3], Y##_f[2]);				    \
    __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,6),_FP_FRAC_WORD_8(_z,5),	    \
		    _FP_FRAC_WORD_8(_z,4), 0,_b_f1,_b_f0,		    \
		    0,_FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4));	    \
    __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,6),_FP_FRAC_WORD_8(_z,5),	    \
		    _FP_FRAC_WORD_8(_z,4), 0,_c_f1,_c_f0,		    \
		    _FP_FRAC_WORD_8(_z,6),_FP_FRAC_WORD_8(_z,5),	    \
		    _FP_FRAC_WORD_8(_z,4));				    \
    __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,6),_FP_FRAC_WORD_8(_z,5),	    \
		    _FP_FRAC_WORD_8(_z,4), 0,_d_f1,_d_f0,		    \
		    _FP_FRAC_WORD_8(_z,6),_FP_FRAC_WORD_8(_z,5),	    \
		    _FP_FRAC_WORD_8(_z,4));				    \
    __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,7),_FP_FRAC_WORD_8(_z,6),	    \
		    _FP_FRAC_WORD_8(_z,5), 0,_e_f1,_e_f0,		    \
		    0,_FP_FRAC_WORD_8(_z,6),_FP_FRAC_WORD_8(_z,5));	    \
    __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,7),_FP_FRAC_WORD_8(_z,6),	    \
		    _FP_FRAC_WORD_8(_z,5), 0,_f_f1,_f_f0,		    \
		    _FP_FRAC_WORD_8(_z,7),_FP_FRAC_WORD_8(_z,6),	    \
		    _FP_FRAC_WORD_8(_z,5));				    \
    doit(_b_f1, _b_f0, X##_f[3], Y##_f[3]);				    \
    __FP_FRAC_ADD_2(_FP_FRAC_WORD_8(_z,7),_FP_FRAC_WORD_8(_z,6),	    \
		    _b_f1,_b_f0,					    \
		    _FP_FRAC_WORD_8(_z,7),_FP_FRAC_WORD_8(_z,6));	    \
									    \
    /* Normalize since we know where the msb of the multiplicands	    \
       were (bit B), we know that the msb of the of the product is	    \
       at either 2B or 2B-1.  */					    \
    _FP_FRAC_SRS_8(_z, wfracbits-1, 2*wfracbits);			    \
    __FP_FRAC_SET_4(R, _FP_FRAC_WORD_8(_z,3), _FP_FRAC_WORD_8(_z,2),	    \
		    _FP_FRAC_WORD_8(_z,1), _FP_FRAC_WORD_8(_z,0));	    \
  } while (0)

#define _FP_MUL_MEAT_4_gmp(wfracbits, R, X, Y)				    \
  do {									    \
    _FP_FRAC_DECL_8(_z);						    \
									    \
    mpn_mul_n(_z_f, _x_f, _y_f, 4);					    \
									    \
    /* Normalize since we know where the msb of the multiplicands	    \
       were (bit B), we know that the msb of the of the product is	    \
       at either 2B or 2B-1.  */					    \
    _FP_FRAC_SRS_8(_z, wfracbits-1, 2*wfracbits);	 		    \
    __FP_FRAC_SET_4(R, _FP_FRAC_WORD_8(_z,3), _FP_FRAC_WORD_8(_z,2),	    \
		    _FP_FRAC_WORD_8(_z,1), _FP_FRAC_WORD_8(_z,0));	    \
  } while (0)

/*
 * Helper utility for _FP_DIV_MEAT_4_udiv:
 * pppp = m * nnn
 */
#define umul_ppppmnnn(p3,p2,p1,p0,m,n2,n1,n0)				    \
  do {									    \
    UWtype _t;								    \
    umul_ppmm(p1,p0,m,n0);						    \
    umul_ppmm(p2,_t,m,n1);						    \
    __FP_FRAC_ADDI_2(p2,p1,_t);						    \
    umul_ppmm(p3,_t,m,n2);						    \
    __FP_FRAC_ADDI_2(p3,p2,_t);						    \
  } while (0)

/*
 * Division algorithms:
 */

#define _FP_DIV_MEAT_4_udiv(fs, R, X, Y)				    \
  do {									    \
    int _i;								    \
    _FP_FRAC_DECL_4(_n); _FP_FRAC_DECL_4(_m);				    \
    _FP_FRAC_SET_4(_n, _FP_ZEROFRAC_4);					    \
    if (_FP_FRAC_GT_4(X, Y))						    \
      {									    \
	_n_f[3] = X##_f[0] << (_FP_W_TYPE_SIZE - 1);			    \
	_FP_FRAC_SRL_4(X, 1);						    \
      }									    \
    else								    \
      R##_e--;								    \
									    \
    /* Normalize, i.e. make the most significant bit of the 		    \
       denominator set. */						    \
    _FP_FRAC_SLL_4(Y, _FP_WFRACXBITS_##fs);				    \
									    \
    for (_i = 3; ; _i--)						    \
      {									    \
        if (X##_f[3] == Y##_f[3])					    \
          {								    \
            /* This is a special case, not an optimization		    \
               (X##_f[3]/Y##_f[3] would not fit into UWtype).		    \
               As X## is guaranteed to be < Y,  R##_f[_i] can be either	    \
               (UWtype)-1 or (UWtype)-2.  */				    \
            R##_f[_i] = -1;						    \
            if (!_i)							    \
	      break;							    \
            __FP_FRAC_SUB_4(X##_f[3], X##_f[2], X##_f[1], X##_f[0],	    \
			    Y##_f[2], Y##_f[1], Y##_f[0], 0,		    \
			    X##_f[2], X##_f[1], X##_f[0], _n_f[_i]);	    \
            _FP_FRAC_SUB_4(X, Y, X);					    \
            if (X##_f[3] > Y##_f[3])					    \
              {								    \
                R##_f[_i] = -2;						    \
                _FP_FRAC_ADD_4(X, Y, X);				    \
              }								    \
          }								    \
        else								    \
          {								    \
            udiv_qrnnd(R##_f[_i], X##_f[3], X##_f[3], X##_f[2], Y##_f[3]);  \
            umul_ppppmnnn(_m_f[3], _m_f[2], _m_f[1], _m_f[0],		    \
			  R##_f[_i], Y##_f[2], Y##_f[1], Y##_f[0]);	    \
            X##_f[2] = X##_f[1];					    \
            X##_f[1] = X##_f[0];					    \
            X##_f[0] = _n_f[_i];					    \
            if (_FP_FRAC_GT_4(_m, X))					    \
              {								    \
                R##_f[_i]--;						    \
                _FP_FRAC_ADD_4(X, Y, X);				    \
                if (_FP_FRAC_GE_4(X, Y) && _FP_FRAC_GT_4(_m, X))	    \
                  {							    \
		    R##_f[_i]--;					    \
		    _FP_FRAC_ADD_4(X, Y, X);				    \
                  }							    \
              }								    \
            _FP_FRAC_DEC_4(X, _m);					    \
            if (!_i)							    \
	      {								    \
		if (!_FP_FRAC_EQ_4(X, _m))				    \
		  R##_f[0] |= _FP_WORK_STICKY;				    \
		break;							    \
	      }								    \
          }								    \
      }									    \
  } while (0)


/*
 * Square root algorithms:
 * We have just one right now, maybe Newton approximation
 * should be added for those machines where division is fast.
 */
 
#define _FP_SQRT_MEAT_4(R, S, T, X, q)				\
  do {								\
    while (q)							\
      {								\
	T##_f[3] = S##_f[3] + q;				\
	if (T##_f[3] <= X##_f[3])				\
	  {							\
	    S##_f[3] = T##_f[3] + q;				\
	    X##_f[3] -= T##_f[3];				\
	    R##_f[3] += q;					\
	  }							\
	_FP_FRAC_SLL_4(X, 1);					\
	q >>= 1;						\
      }								\
    q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1);			\
    while (q)							\
      {								\
	T##_f[2] = S##_f[2] + q;				\
	T##_f[3] = S##_f[3];					\
	if (T##_f[3] < X##_f[3] || 				\
	    (T##_f[3] == X##_f[3] && T##_f[2] <= X##_f[2]))	\
	  {							\
	    S##_f[2] = T##_f[2] + q;				\
	    S##_f[3] += (T##_f[2] > S##_f[2]);			\
	    __FP_FRAC_DEC_2(X##_f[3], X##_f[2],			\
			    T##_f[3], T##_f[2]);		\
	    R##_f[2] += q;					\
	  }							\
	_FP_FRAC_SLL_4(X, 1);					\
	q >>= 1;						\
      }								\
    q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1);			\
    while (q)							\
      {								\
	T##_f[1] = S##_f[1] + q;				\
	T##_f[2] = S##_f[2];					\
	T##_f[3] = S##_f[3];					\
	if (T##_f[3] < X##_f[3] || 				\
	    (T##_f[3] == X##_f[3] && (T##_f[2] < X##_f[2] ||	\
	     (T##_f[2] == X##_f[2] && T##_f[1] <= X##_f[1]))))	\
	  {							\
	    S##_f[1] = T##_f[1] + q;				\
	    S##_f[2] += (T##_f[1] > S##_f[1]);			\
	    S##_f[3] += (T##_f[2] > S##_f[2]);			\
	    __FP_FRAC_DEC_3(X##_f[3], X##_f[2], X##_f[1],	\
	    		    T##_f[3], T##_f[2], T##_f[1]);	\
	    R##_f[1] += q;					\
	  }							\
	_FP_FRAC_SLL_4(X, 1);					\
	q >>= 1;						\
      }								\
    q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1);			\
    while (q != _FP_WORK_ROUND)					\
      {								\
	T##_f[0] = S##_f[0] + q;				\
	T##_f[1] = S##_f[1];					\
	T##_f[2] = S##_f[2];					\
	T##_f[3] = S##_f[3];					\
	if (_FP_FRAC_GE_4(X,T))					\
	  {							\
	    S##_f[0] = T##_f[0] + q;				\
	    S##_f[1] += (T##_f[0] > S##_f[0]);			\
	    S##_f[2] += (T##_f[1] > S##_f[1]);			\
	    S##_f[3] += (T##_f[2] > S##_f[2]);			\
	    _FP_FRAC_DEC_4(X, T);				\
	    R##_f[0] += q;					\
	  }							\
	_FP_FRAC_SLL_4(X, 1);					\
	q >>= 1;						\
      }								\
    if (!_FP_FRAC_ZEROP_4(X))					\
      {								\
	if (_FP_FRAC_GT_4(X,S))					\
	  R##_f[0] |= _FP_WORK_ROUND;				\
	R##_f[0] |= _FP_WORK_STICKY;				\
      }								\
  } while (0)


/*
 * Internals 
 */

#define __FP_FRAC_SET_4(X,I3,I2,I1,I0)					\
  (X##_f[3] = I3, X##_f[2] = I2, X##_f[1] = I1, X##_f[0] = I0)

#ifndef __FP_FRAC_ADD_3
#define __FP_FRAC_ADD_3(r2,r1,r0,x2,x1,x0,y2,y1,y0)		\
  do {								\
    _FP_W_TYPE _c1, _c2;					\
    r0 = x0 + y0;						\
    _c1 = r0 < x0;						\
    r1 = x1 + y1;						\
    _c2 = r1 < x1;						\
    r1 += _c1;							\
    _c2 |= r1 < _c1;						\
    r2 = x2 + y2 + _c2;						\
  } while (0)
#endif

#ifndef __FP_FRAC_ADD_4
#define __FP_FRAC_ADD_4(r3,r2,r1,r0,x3,x2,x1,x0,y3,y2,y1,y0)	\
  do {								\
    _FP_W_TYPE _c1, _c2, _c3;					\
    r0 = x0 + y0;						\
    _c1 = r0 < x0;						\
    r1 = x1 + y1;						\
    _c2 = r1 < x1;						\
    r1 += _c1;							\
    _c2 |= r1 < _c1;						\
    r2 = x2 + y2;						\
    _c3 = r2 < x2;						\
    r2 += _c2;							\
    _c3 |= r2 < _c2;						\
    r3 = x3 + y3 + _c3;						\
  } while (0)
#endif

#ifndef __FP_FRAC_SUB_3
#define __FP_FRAC_SUB_3(r2,r1,r0,x2,x1,x0,y2,y1,y0)		\
  do {								\
    _FP_W_TYPE _c1, _c2;					\
    r0 = x0 - y0;						\
    _c1 = r0 > x0;						\
    r1 = x1 - y1;						\
    _c2 = r1 > x1;						\
    r1 -= _c1;							\
    _c2 |= _c1 && (y1 == x1);					\
    r2 = x2 - y2 - _c2;						\
  } while (0)
#endif

#ifndef __FP_FRAC_SUB_4
#define __FP_FRAC_SUB_4(r3,r2,r1,r0,x3,x2,x1,x0,y3,y2,y1,y0)	\
  do {								\
    _FP_W_TYPE _c1, _c2, _c3;					\
    r0 = x0 - y0;						\
    _c1 = r0 > x0;						\
    r1 = x1 - y1;						\
    _c2 = r1 > x1;						\
    r1 -= _c1;							\
    _c2 |= _c1 && (y1 == x1);					\
    r2 = x2 - y2;						\
    _c3 = r2 > x2;						\
    r2 -= _c2;							\
    _c3 |= _c2 && (y2 == x2);					\
    r3 = x3 - y3 - _c3;						\
  } while (0)
#endif

#ifndef __FP_FRAC_DEC_3
#define __FP_FRAC_DEC_3(x2,x1,x0,y2,y1,y0)				\
  do {									\
    UWtype _t0, _t1, _t2;						\
    _t0 = x0, _t1 = x1, _t2 = x2;					\
    __FP_FRAC_SUB_3 (x2, x1, x0, _t2, _t1, _t0, y2, y1, y0);		\
  } while (0)
#endif

#ifndef __FP_FRAC_DEC_4
#define __FP_FRAC_DEC_4(x3,x2,x1,x0,y3,y2,y1,y0)			\
  do {									\
    UWtype _t0, _t1, _t2, _t3;						\
    _t0 = x0, _t1 = x1, _t2 = x2, _t3 = x3;				\
    __FP_FRAC_SUB_4 (x3,x2,x1,x0,_t3,_t2,_t1,_t0, y3,y2,y1,y0);		\
  } while (0)
#endif

#ifndef __FP_FRAC_ADDI_4
#define __FP_FRAC_ADDI_4(x3,x2,x1,x0,i)					\
  do {									\
    UWtype _t;								\
    _t = ((x0 += i) < i);						\
    x1 += _t; _t = (x1 < _t);						\
    x2 += _t; _t = (x2 < _t);						\
    x3 += _t;								\
  } while (0)
#endif

/* Convert FP values between word sizes. This appears to be more
 * complicated than I'd have expected it to be, so these might be
 * wrong... These macros are in any case somewhat bogus because they
 * use information about what various FRAC_n variables look like 
 * internally [eg, that 2 word vars are X_f0 and x_f1]. But so do
 * the ones in op-2.h and op-1.h. 
 */
#define _FP_FRAC_COPY_1_4(D, S)		(D##_f = S##_f[0])

#define _FP_FRAC_COPY_2_4(D, S)			\
do {						\
  D##_f0 = S##_f[0];				\
  D##_f1 = S##_f[1];				\
} while (0)

/* Assembly/disassembly for converting to/from integral types.  
 * No shifting or overflow handled here.
 */
/* Put the FP value X into r, which is an integer of size rsize. */
#define _FP_FRAC_ASSEMBLE_4(r, X, rsize)				\
  do {									\
    if (rsize <= _FP_W_TYPE_SIZE)					\
      r = X##_f[0];							\
    else if (rsize <= 2*_FP_W_TYPE_SIZE)				\
    {									\
      r = X##_f[1];							\
      r <<= _FP_W_TYPE_SIZE;						\
      r += X##_f[0];							\
    }									\
    else								\
    {									\
      /* I'm feeling lazy so we deal with int == 3words (implausible)*/	\
      /* and int == 4words as a single case.			 */	\
      r = X##_f[3];							\
      r <<= _FP_W_TYPE_SIZE;						\
      r += X##_f[2];							\
      r <<= _FP_W_TYPE_SIZE;						\
      r += X##_f[1];							\
      r <<= _FP_W_TYPE_SIZE;						\
      r += X##_f[0];							\
    }									\
  } while (0)

/* "No disassemble Number Five!" */
/* move an integer of size rsize into X's fractional part. We rely on
 * the _f[] array consisting of words of size _FP_W_TYPE_SIZE to avoid
 * having to mask the values we store into it.
 */
#define _FP_FRAC_DISASSEMBLE_4(X, r, rsize)				\
  do {									\
    X##_f[0] = r;							\
    X##_f[1] = (rsize <= _FP_W_TYPE_SIZE ? 0 : r >> _FP_W_TYPE_SIZE);	\
    X##_f[2] = (rsize <= 2*_FP_W_TYPE_SIZE ? 0 : r >> 2*_FP_W_TYPE_SIZE); \
    X##_f[3] = (rsize <= 3*_FP_W_TYPE_SIZE ? 0 : r >> 3*_FP_W_TYPE_SIZE); \
  } while (0);

#define _FP_FRAC_COPY_4_1(D, S)			\
do {						\
  D##_f[0] = S##_f;				\
  D##_f[1] = D##_f[2] = D##_f[3] = 0;		\
} while (0)

#define _FP_FRAC_COPY_4_2(D, S)			\
do {						\
  D##_f[0] = S##_f0;				\
  D##_f[1] = S##_f1;				\
  D##_f[2] = D##_f[3] = 0;			\
} while (0)

#define _FP_FRAC_COPY_4_4(D,S)	_FP_FRAC_COPY_4(D,S)


//#include "op-8.h"

#define _FP_FRAC_DECL_8(X)	_FP_W_TYPE X##_f[8]
#define _FP_FRAC_HIGH_8(X)	(X##_f[7])
#define _FP_FRAC_LOW_8(X)	(X##_f[0])
#define _FP_FRAC_WORD_8(X,w)	(X##_f[w])

#define _FP_FRAC_SLL_8(X,N)						\
  do {									\
    _FP_I_TYPE _up, _down, _skip, _i;					\
    _skip = (N) / _FP_W_TYPE_SIZE;					\
    _up = (N) % _FP_W_TYPE_SIZE;					\
    _down = _FP_W_TYPE_SIZE - _up;					\
    if (!_up)								\
      for (_i = 7; _i >= _skip; --_i)					\
	X##_f[_i] = X##_f[_i-_skip];					\
    else								\
      {									\
	for (_i = 7; _i > _skip; --_i)					\
	  X##_f[_i] = X##_f[_i-_skip] << _up				\
		      | X##_f[_i-_skip-1] >> _down;			\
	X##_f[_i--] = X##_f[0] << _up; 					\
      }									\
    for (; _i >= 0; --_i)						\
      X##_f[_i] = 0;							\
  } while (0)

#define _FP_FRAC_SRL_8(X,N)						\
  do {									\
    _FP_I_TYPE _up, _down, _skip, _i;					\
    _skip = (N) / _FP_W_TYPE_SIZE;					\
    _down = (N) % _FP_W_TYPE_SIZE;					\
    _up = _FP_W_TYPE_SIZE - _down;					\
    if (!_down)								\
      for (_i = 0; _i <= 7-_skip; ++_i)					\
	X##_f[_i] = X##_f[_i+_skip];					\
    else								\
      {									\
	for (_i = 0; _i < 7-_skip; ++_i)				\
	  X##_f[_i] = X##_f[_i+_skip] >> _down				\
		      | X##_f[_i+_skip+1] << _up;			\
	X##_f[_i++] = X##_f[7] >> _down;				\
      }									\
    for (; _i < 8; ++_i)						\
      X##_f[_i] = 0;							\
  } while (0)


/* Right shift with sticky-lsb. 
 * What this actually means is that we do a standard right-shift,
 * but that if any of the bits that fall off the right hand side
 * were one then we always set the LSbit.
 */
#define _FP_FRAC_SRS_8(X,N,size)					\
  do {									\
    _FP_I_TYPE _up, _down, _skip, _i;					\
    _FP_W_TYPE _s;							\
    _skip = (N) / _FP_W_TYPE_SIZE;					\
    _down = (N) % _FP_W_TYPE_SIZE;					\
    _up = _FP_W_TYPE_SIZE - _down;					\
    for (_s = _i = 0; _i < _skip; ++_i)					\
      _s |= X##_f[_i];							\
    if (!_down)								\
      for (_i = 0; _i <= 7-_skip; ++_i)					\
	X##_f[_i] = X##_f[_i+_skip];					\
    else								\
      {									\
	_s |= X##_f[_i] << _up;						\
	for (_i = 0; _i < 7-_skip; ++_i)				\
	  X##_f[_i] = X##_f[_i+_skip] >> _down				\
		      | X##_f[_i+_skip+1] << _up;			\
	X##_f[_i++] = X##_f[7] >> _down;				\
      }									\
    for (; _i < 8; ++_i)						\
      X##_f[_i] = 0;							\
    /* don't fix the LSB until the very end when we're sure f[0] is stable */	\
    X##_f[0] |= (_s != 0);						\
  } while (0)


//#include "op-common.h"

#define _FP_DECL(wc, X)						\
  _FP_I_TYPE X##_c __attribute__((unused)), X##_s, X##_e;	\
  _FP_FRAC_DECL_##wc(X)

/*
 * Finish truely unpacking a native fp value by classifying the kind
 * of fp value and normalizing both the exponent and the fraction.
 */

#define _FP_UNPACK_CANONICAL(fs, wc, X)					\
do {									\
  switch (X##_e)							\
  {									\
  default:								\
    _FP_FRAC_HIGH_RAW_##fs(X) |= _FP_IMPLBIT_##fs;			\
    _FP_FRAC_SLL_##wc(X, _FP_WORKBITS);					\
    X##_e -= _FP_EXPBIAS_##fs;						\
    X##_c = FP_CLS_NORMAL;						\
    break;								\
									\
  case 0:								\
    if (_FP_FRAC_ZEROP_##wc(X))						\
      X##_c = FP_CLS_ZERO;						\
    else								\
      {									\
	/* a denormalized number */					\
	_FP_I_TYPE _shift;						\
	_FP_FRAC_CLZ_##wc(_shift, X);					\
	_shift -= _FP_FRACXBITS_##fs;					\
	_FP_FRAC_SLL_##wc(X, (_shift+_FP_WORKBITS));			\
	X##_e -= _FP_EXPBIAS_##fs - 1 + _shift;				\
	X##_c = FP_CLS_NORMAL;						\
	FP_SET_EXCEPTION(FP_EX_DENORM);					\
      }									\
    break;								\
									\
  case _FP_EXPMAX_##fs:							\
    if (_FP_FRAC_ZEROP_##wc(X))						\
      X##_c = FP_CLS_INF;						\
    else								\
      {									\
	X##_c = FP_CLS_NAN;						\
	/* Check for signaling NaN */					\
	if (!(_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs))		\
	  FP_SET_EXCEPTION(FP_EX_INVALID);				\
      }									\
    break;								\
  }									\
} while (0)

/* Finish unpacking an fp value in semi-raw mode: the mantissa is
   shifted by _FP_WORKBITS but the implicit MSB is not inserted and
   other classification is not done.  */
#define _FP_UNPACK_SEMIRAW(fs, wc, X)	_FP_FRAC_SLL_##wc(X, _FP_WORKBITS)

/* A semi-raw value has overflowed to infinity.  Adjust the mantissa
   and exponent appropriately.  */
#define _FP_OVERFLOW_SEMIRAW(fs, wc, X)			\
do {							\
  if (FP_ROUNDMODE == FP_RND_NEAREST			\
      || (FP_ROUNDMODE == FP_RND_PINF && !X##_s)	\
      || (FP_ROUNDMODE == FP_RND_MINF && X##_s))	\
    {							\
      X##_e = _FP_EXPMAX_##fs;				\
      _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc);		\
    }							\
  else							\
    {							\
      X##_e = _FP_EXPMAX_##fs - 1;			\
      _FP_FRAC_SET_##wc(X, _FP_MAXFRAC_##wc);		\
    }							\
    FP_SET_EXCEPTION(FP_EX_INEXACT);			\
    FP_SET_EXCEPTION(FP_EX_OVERFLOW);			\
} while (0)

/* Check for a semi-raw value being a signaling NaN and raise the
   invalid exception if so.  */
#define _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, X)			\
do {								\
  if (X##_e == _FP_EXPMAX_##fs					\
      && !_FP_FRAC_ZEROP_##wc(X)				\
      && !(_FP_FRAC_HIGH_##fs(X) & _FP_QNANBIT_SH_##fs))	\
    FP_SET_EXCEPTION(FP_EX_INVALID);				\
} while (0)

/* Choose a NaN result from an operation on two semi-raw NaN
   values.  */
#define _FP_CHOOSENAN_SEMIRAW(fs, wc, R, X, Y, OP)			\
do {									\
  /* _FP_CHOOSENAN expects raw values, so shift as required.  */	\
  _FP_FRAC_SRL_##wc(X, _FP_WORKBITS);					\
  _FP_FRAC_SRL_##wc(Y, _FP_WORKBITS);					\
  _FP_CHOOSENAN(fs, wc, R, X, Y, OP);					\
  _FP_FRAC_SLL_##wc(R, _FP_WORKBITS);					\
} while (0)

/* Test whether a biased exponent is normal (not zero or maximum).  */
#define _FP_EXP_NORMAL(fs, wc, X)	(((X##_e + 1) & _FP_EXPMAX_##fs) > 1)

/* Prepare to pack an fp value in semi-raw mode: the mantissa is
   rounded and shifted right, with the rounding possibly increasing
   the exponent (including changing a finite value to infinity).  */
#define _FP_PACK_SEMIRAW(fs, wc, X)				\
do {								\
  _FP_ROUND(wc, X);						\
  if (_FP_FRAC_HIGH_##fs(X)					\
      & (_FP_OVERFLOW_##fs >> 1))				\
    {								\
      _FP_FRAC_HIGH_##fs(X) &= ~(_FP_OVERFLOW_##fs >> 1);	\
      X##_e++;							\
      if (X##_e == _FP_EXPMAX_##fs)				\
	_FP_OVERFLOW_SEMIRAW(fs, wc, X);			\
    }								\
  _FP_FRAC_SRL_##wc(X, _FP_WORKBITS);				\
  if (!_FP_EXP_NORMAL(fs, wc, X) && !_FP_FRAC_ZEROP_##wc(X))	\
    {								\
      if (X##_e == 0)						\
	{							\
	  if ((FP_CUR_EXCEPTIONS & FP_EX_INEXACT)		\
	      || (FP_TRAPPING_EXCEPTIONS & FP_EX_UNDERFLOW))	\
	    FP_SET_EXCEPTION(FP_EX_UNDERFLOW);			\
	}							\
      else							\
	{							\
	  if (!_FP_KEEPNANFRACP)				\
	    {							\
	      _FP_FRAC_SET_##wc(X, _FP_NANFRAC_##fs);		\
	      X##_s = _FP_NANSIGN_##fs;				\
	    }							\
	  else							\
	    _FP_FRAC_HIGH_RAW_##fs(X) |= _FP_QNANBIT_##fs;	\
	}							\
    }								\
} while (0)

/*
 * Before packing the bits back into the native fp result, take care
 * of such mundane things as rounding and overflow.  Also, for some
 * kinds of fp values, the original parts may not have been fully
 * extracted -- but that is ok, we can regenerate them now.
 */

#define _FP_PACK_CANONICAL(fs, wc, X)				\
do {								\
  switch (X##_c)						\
  {								\
  case FP_CLS_NORMAL:						\
    X##_e += _FP_EXPBIAS_##fs;					\
    if (X##_e > 0)						\
      {								\
	_FP_ROUND(wc, X);					\
	if (_FP_FRAC_OVERP_##wc(fs, X))				\
	  {							\
	    _FP_FRAC_CLEAR_OVERP_##wc(fs, X);			\
	    X##_e++;						\
	  }							\
	_FP_FRAC_SRL_##wc(X, _FP_WORKBITS);			\
	if (X##_e >= _FP_EXPMAX_##fs)				\
	  {							\
	    /* overflow */					\
	    switch (FP_ROUNDMODE)				\
	      {							\
	      case FP_RND_NEAREST:				\
		X##_c = FP_CLS_INF;				\
		break;						\
	      case FP_RND_PINF:					\
		if (!X##_s) X##_c = FP_CLS_INF;			\
		break;						\
	      case FP_RND_MINF:					\
		if (X##_s) X##_c = FP_CLS_INF;			\
		break;						\
	      }							\
	    if (X##_c == FP_CLS_INF)				\
	      {							\
		/* Overflow to infinity */			\
		X##_e = _FP_EXPMAX_##fs;			\
		_FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc);	\
	      }							\
	    else						\
	      {							\
		/* Overflow to maximum normal */		\
		X##_e = _FP_EXPMAX_##fs - 1;			\
		_FP_FRAC_SET_##wc(X, _FP_MAXFRAC_##wc);		\
	      }							\
	    FP_SET_EXCEPTION(FP_EX_OVERFLOW);			\
            FP_SET_EXCEPTION(FP_EX_INEXACT);			\
	  }							\
      }								\
    else							\
      {								\
	/* we've got a denormalized number */			\
	X##_e = -X##_e + 1;					\
	if (X##_e <= _FP_WFRACBITS_##fs)			\
	  {							\
	    _FP_FRAC_SRS_##wc(X, X##_e, _FP_WFRACBITS_##fs);	\
	    _FP_ROUND(wc, X);					\
	    if (_FP_FRAC_HIGH_##fs(X)				\
		& (_FP_OVERFLOW_##fs >> 1))			\
	      {							\
	        X##_e = 1;					\
	        _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc);	\
		FP_SET_EXCEPTION(FP_EX_INEXACT);		\
	      }							\
	    else						\
	      {							\
		X##_e = 0;					\
		_FP_FRAC_SRL_##wc(X, _FP_WORKBITS);		\
	      }							\
	    if ((FP_CUR_EXCEPTIONS & FP_EX_INEXACT)		\
		|| (FP_TRAPPING_EXCEPTIONS & FP_EX_UNDERFLOW))	\
	      FP_SET_EXCEPTION(FP_EX_UNDERFLOW);		\
	  }							\
	else							\
	  {							\
	    /* underflow to zero */				\
	    X##_e = 0;						\
	    if (!_FP_FRAC_ZEROP_##wc(X))			\
	      {							\
	        _FP_FRAC_SET_##wc(X, _FP_MINFRAC_##wc);		\
	        _FP_ROUND(wc, X);				\
	        _FP_FRAC_LOW_##wc(X) >>= (_FP_WORKBITS);	\
	      }							\
	    FP_SET_EXCEPTION(FP_EX_UNDERFLOW);			\
	  }							\
      }								\
    break;							\
								\
  case FP_CLS_ZERO:						\
    X##_e = 0;							\
    _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc);			\
    break;							\
								\
  case FP_CLS_INF:						\
    X##_e = _FP_EXPMAX_##fs;					\
    _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc);			\
    break;							\
								\
  case FP_CLS_NAN:						\
    X##_e = _FP_EXPMAX_##fs;					\
    if (!_FP_KEEPNANFRACP)					\
      {								\
	_FP_FRAC_SET_##wc(X, _FP_NANFRAC_##fs);			\
	X##_s = _FP_NANSIGN_##fs;				\
      }								\
    else							\
      _FP_FRAC_HIGH_RAW_##fs(X) |= _FP_QNANBIT_##fs;		\
    break;							\
  }								\
} while (0)

/* This one accepts raw argument and not cooked,  returns
 * 1 if X is a signaling NaN.
 */
#define _FP_ISSIGNAN(fs, wc, X)					\
({								\
  int __ret = 0;						\
  if (X##_e == _FP_EXPMAX_##fs)					\
    {								\
      if (!_FP_FRAC_ZEROP_##wc(X)				\
	  && !(_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs))	\
	__ret = 1;						\
    }								\
  __ret;							\
})





/* Addition on semi-raw values.  */
#define _FP_ADD_INTERNAL(fs, wc, R, X, Y, OP)				 \
do {									 \
  if (X##_s == Y##_s)							 \
    {									 \
      /* Addition.  */							 \
      R##_s = X##_s;							 \
      int ediff = X##_e - Y##_e;					 \
      if (ediff > 0)							 \
	{								 \
	  R##_e = X##_e;						 \
	  if (Y##_e == 0)						 \
	    {								 \
	      /* Y is zero or denormalized.  */				 \
	      if (_FP_FRAC_ZEROP_##wc(Y))				 \
		{							 \
		  _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, X);			 \
		  _FP_FRAC_COPY_##wc(R, X);				 \
		  goto add_done;					 \
		}							 \
	      else							 \
		{							 \
		  FP_SET_EXCEPTION(FP_EX_DENORM);			 \
		  ediff--;						 \
		  if (ediff == 0)					 \
		    {							 \
		      _FP_FRAC_ADD_##wc(R, X, Y);			 \
		      goto add3;					 \
		    }							 \
		  if (X##_e == _FP_EXPMAX_##fs)				 \
		    {							 \
		      _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, X);		 \
		      _FP_FRAC_COPY_##wc(R, X);				 \
		      goto add_done;					 \
		    }							 \
		  goto add1;						 \
		}							 \
	    }								 \
	  else if (X##_e == _FP_EXPMAX_##fs)				 \
	    {								 \
	      /* X is NaN or Inf, Y is normal.  */			 \
	      _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, X);			 \
	      _FP_FRAC_COPY_##wc(R, X);					 \
	      goto add_done;						 \
	    }								 \
									 \
	  /* Insert implicit MSB of Y.  */				 \
	  _FP_FRAC_HIGH_##fs(Y) |= _FP_IMPLBIT_SH_##fs;			 \
									 \
	add1:								 \
	  /* Shift the mantissa of Y to the right EDIFF steps;		 \
	     remember to account later for the implicit MSB of X.  */	 \
	  if (ediff <= _FP_WFRACBITS_##fs)				 \
	    _FP_FRAC_SRS_##wc(Y, ediff, _FP_WFRACBITS_##fs);		 \
	  else if (!_FP_FRAC_ZEROP_##wc(Y))				 \
	    _FP_FRAC_SET_##wc(Y, _FP_MINFRAC_##wc);			 \
	  _FP_FRAC_ADD_##wc(R, X, Y);					 \
	}								 \
      else if (ediff < 0)						 \
	{								 \
	  ediff = -ediff;						 \
	  R##_e = Y##_e;						 \
	  if (X##_e == 0)						 \
	    {								 \
	      /* X is zero or denormalized.  */				 \
	      if (_FP_FRAC_ZEROP_##wc(X))				 \
		{							 \
		  _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, Y);			 \
		  _FP_FRAC_COPY_##wc(R, Y);				 \
		  goto add_done;					 \
		}							 \
	      else							 \
		{							 \
		  FP_SET_EXCEPTION(FP_EX_DENORM);			 \
		  ediff--;						 \
		  if (ediff == 0)					 \
		    {							 \
		      _FP_FRAC_ADD_##wc(R, Y, X);			 \
		      goto add3;					 \
		    }							 \
		  if (Y##_e == _FP_EXPMAX_##fs)				 \
		    {							 \
		      _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, Y);		 \
		      _FP_FRAC_COPY_##wc(R, Y);				 \
		      goto add_done;					 \
		    }							 \
		  goto add2;						 \
		}							 \
	    }								 \
	  else if (Y##_e == _FP_EXPMAX_##fs)				 \
	    {								 \
	      /* Y is NaN or Inf, X is normal.  */			 \
	      _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, Y);			 \
	      _FP_FRAC_COPY_##wc(R, Y);					 \
	      goto add_done;						 \
	    }								 \
									 \
	  /* Insert implicit MSB of X.  */				 \
	  _FP_FRAC_HIGH_##fs(X) |= _FP_IMPLBIT_SH_##fs;			 \
									 \
	add2:								 \
	  /* Shift the mantissa of X to the right EDIFF steps;		 \
	     remember to account later for the implicit MSB of Y.  */	 \
	  if (ediff <= _FP_WFRACBITS_##fs)				 \
	    _FP_FRAC_SRS_##wc(X, ediff, _FP_WFRACBITS_##fs);		 \
	  else if (!_FP_FRAC_ZEROP_##wc(X))				 \
	    _FP_FRAC_SET_##wc(X, _FP_MINFRAC_##wc);			 \
	  _FP_FRAC_ADD_##wc(R, Y, X);					 \
	}								 \
      else								 \
	{								 \
	  /* ediff == 0.  */						 \
	  if (!_FP_EXP_NORMAL(fs, wc, X))				 \
	    {								 \
	      if (X##_e == 0)						 \
		{							 \
		  /* X and Y are zero or denormalized.  */		 \
		  R##_e = 0;						 \
		  if (_FP_FRAC_ZEROP_##wc(X))				 \
		    {							 \
		      if (!_FP_FRAC_ZEROP_##wc(Y))			 \
			FP_SET_EXCEPTION(FP_EX_DENORM);			 \
		      _FP_FRAC_COPY_##wc(R, Y);				 \
		      goto add_done;					 \
		    }							 \
		  else if (_FP_FRAC_ZEROP_##wc(Y))			 \
		    {							 \
		      FP_SET_EXCEPTION(FP_EX_DENORM);			 \
		      _FP_FRAC_COPY_##wc(R, X);				 \
		      goto add_done;					 \
		    }							 \
		  else							 \
		    {							 \
		      FP_SET_EXCEPTION(FP_EX_DENORM);			 \
		      _FP_FRAC_ADD_##wc(R, X, Y);			 \
		      if (_FP_FRAC_HIGH_##fs(R) & _FP_IMPLBIT_SH_##fs)	 \
			{						 \
			  /* Normalized result.  */			 \
			  _FP_FRAC_HIGH_##fs(R)				 \
			    &= ~(_FP_W_TYPE)_FP_IMPLBIT_SH_##fs;	 \
			  R##_e = 1;					 \
			}						 \
		      goto add_done;					 \
		    }							 \
		}							 \
	      else							 \
		{							 \
		  /* X and Y are NaN or Inf.  */			 \
		  _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, X);			 \
		  _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, Y);			 \
		  R##_e = _FP_EXPMAX_##fs;				 \
		  if (_FP_FRAC_ZEROP_##wc(X))				 \
		    _FP_FRAC_COPY_##wc(R, Y);				 \
		  else if (_FP_FRAC_ZEROP_##wc(Y))			 \
		    _FP_FRAC_COPY_##wc(R, X);				 \
		  else							 \
		    _FP_CHOOSENAN_SEMIRAW(fs, wc, R, X, Y, OP);		 \
		  goto add_done;					 \
		}							 \
	    }								 \
	  /* The exponents of X and Y, both normal, are equal.  The	 \
	     implicit MSBs will always add to increase the		 \
	     exponent.  */						 \
	  _FP_FRAC_ADD_##wc(R, X, Y);					 \
	  R##_e = X##_e + 1;						 \
	  _FP_FRAC_SRS_##wc(R, 1, _FP_WFRACBITS_##fs);			 \
	  if (R##_e == _FP_EXPMAX_##fs)					 \
	    /* Overflow to infinity (depending on rounding mode).  */	 \
	    _FP_OVERFLOW_SEMIRAW(fs, wc, R);				 \
	  goto add_done;						 \
	}								 \
    add3:								 \
      if (_FP_FRAC_HIGH_##fs(R) & _FP_IMPLBIT_SH_##fs)			 \
	{								 \
	  /* Overflow.  */						 \
	  _FP_FRAC_HIGH_##fs(R) &= ~(_FP_W_TYPE)_FP_IMPLBIT_SH_##fs;	 \
	  R##_e++;							 \
	  _FP_FRAC_SRS_##wc(R, 1, _FP_WFRACBITS_##fs);			 \
	  if (R##_e == _FP_EXPMAX_##fs)					 \
	    /* Overflow to infinity (depending on rounding mode).  */	 \
	    _FP_OVERFLOW_SEMIRAW(fs, wc, R);				 \
	}								 \
    add_done: ;								 \
    }									 \
  else									 \
    {									 \
      /* Subtraction.  */						 \
      int ediff = X##_e - Y##_e;					 \
      if (ediff > 0)							 \
	{								 \
	  R##_e = X##_e;						 \
	  R##_s = X##_s;						 \
	  if (Y##_e == 0)						 \
	    {								 \
	      /* Y is zero or denormalized.  */				 \
	      if (_FP_FRAC_ZEROP_##wc(Y))				 \
		{							 \
		  _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, X);			 \
		  _FP_FRAC_COPY_##wc(R, X);				 \
		  goto sub_done;					 \
		}							 \
	      else							 \
		{							 \
		  FP_SET_EXCEPTION(FP_EX_DENORM);			 \
		  ediff--;						 \
		  if (ediff == 0)					 \
		    {							 \
		      _FP_FRAC_SUB_##wc(R, X, Y);			 \
		      goto sub3;					 \
		    }							 \
		  if (X##_e == _FP_EXPMAX_##fs)				 \
		    {							 \
		      _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, X);		 \
		      _FP_FRAC_COPY_##wc(R, X);				 \
		      goto sub_done;					 \
		    }							 \
		  goto sub1;						 \
		}							 \
	    }								 \
	  else if (X##_e == _FP_EXPMAX_##fs)				 \
	    {								 \
	      /* X is NaN or Inf, Y is normal.  */			 \
	      _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, X);			 \
	      _FP_FRAC_COPY_##wc(R, X);					 \
	      goto sub_done;						 \
	    }								 \
									 \
	  /* Insert implicit MSB of Y.  */				 \
	  _FP_FRAC_HIGH_##fs(Y) |= _FP_IMPLBIT_SH_##fs;			 \
									 \
	sub1:								 \
	  /* Shift the mantissa of Y to the right EDIFF steps;		 \
	     remember to account later for the implicit MSB of X.  */	 \
	  if (ediff <= _FP_WFRACBITS_##fs)				 \
	    _FP_FRAC_SRS_##wc(Y, ediff, _FP_WFRACBITS_##fs);		 \
	  else if (!_FP_FRAC_ZEROP_##wc(Y))				 \
	    _FP_FRAC_SET_##wc(Y, _FP_MINFRAC_##wc);			 \
	  _FP_FRAC_SUB_##wc(R, X, Y);					 \
	}								 \
      else if (ediff < 0)						 \
	{								 \
	  ediff = -ediff;						 \
	  R##_e = Y##_e;						 \
	  R##_s = Y##_s;						 \
	  if (X##_e == 0)						 \
	    {								 \
	      /* X is zero or denormalized.  */				 \
	      if (_FP_FRAC_ZEROP_##wc(X))				 \
		{							 \
		  _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, Y);			 \
		  _FP_FRAC_COPY_##wc(R, Y);				 \
		  goto sub_done;					 \
		}							 \
	      else							 \
		{							 \
		  FP_SET_EXCEPTION(FP_EX_DENORM);			 \
		  ediff--;						 \
		  if (ediff == 0)					 \
		    {							 \
		      _FP_FRAC_SUB_##wc(R, Y, X);			 \
		      goto sub3;					 \
		    }							 \
		  if (Y##_e == _FP_EXPMAX_##fs)				 \
		    {							 \
		      _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, Y);		 \
		      _FP_FRAC_COPY_##wc(R, Y);				 \
		      goto sub_done;					 \
		    }							 \
		  goto sub2;						 \
		}							 \
	    }								 \
	  else if (Y##_e == _FP_EXPMAX_##fs)				 \
	    {								 \
	      /* Y is NaN or Inf, X is normal.  */			 \
	      _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, Y);			 \
	      _FP_FRAC_COPY_##wc(R, Y);					 \
	      goto sub_done;						 \
	    }								 \
									 \
	  /* Insert implicit MSB of X.  */				 \
	  _FP_FRAC_HIGH_##fs(X) |= _FP_IMPLBIT_SH_##fs;			 \
									 \
	sub2:								 \
	  /* Shift the mantissa of X to the right EDIFF steps;		 \
	     remember to account later for the implicit MSB of Y.  */	 \
	  if (ediff <= _FP_WFRACBITS_##fs)				 \
	    _FP_FRAC_SRS_##wc(X, ediff, _FP_WFRACBITS_##fs);		 \
	  else if (!_FP_FRAC_ZEROP_##wc(X))				 \
	    _FP_FRAC_SET_##wc(X, _FP_MINFRAC_##wc);			 \
	  _FP_FRAC_SUB_##wc(R, Y, X);					 \
	}								 \
      else								 \
	{								 \
	  /* ediff == 0.  */						 \
	  if (!_FP_EXP_NORMAL(fs, wc, X))				 \
	    {								 \
	      if (X##_e == 0)						 \
		{							 \
		  /* X and Y are zero or denormalized.  */		 \
		  R##_e = 0;						 \
		  if (_FP_FRAC_ZEROP_##wc(X))				 \
		    {							 \
		      _FP_FRAC_COPY_##wc(R, Y);				 \
		      if (_FP_FRAC_ZEROP_##wc(Y))			 \
			R##_s = (FP_ROUNDMODE == FP_RND_MINF);		 \
		      else						 \
			{						 \
			  FP_SET_EXCEPTION(FP_EX_DENORM);		 \
			  R##_s = Y##_s;				 \
			}						 \
		      goto sub_done;					 \
		    }							 \
		  else if (_FP_FRAC_ZEROP_##wc(Y))			 \
		    {							 \
		      FP_SET_EXCEPTION(FP_EX_DENORM);			 \
		      _FP_FRAC_COPY_##wc(R, X);				 \
		      R##_s = X##_s;					 \
		      goto sub_done;					 \
		    }							 \
		  else							 \
		    {							 \
		      FP_SET_EXCEPTION(FP_EX_DENORM);			 \
		      _FP_FRAC_SUB_##wc(R, X, Y);			 \
		      R##_s = X##_s;					 \
		      if (_FP_FRAC_HIGH_##fs(R) & _FP_IMPLBIT_SH_##fs)	 \
			{						 \
			  /* |X| < |Y|, negate result.  */		 \
			  _FP_FRAC_SUB_##wc(R, Y, X);			 \
			  R##_s = Y##_s;				 \
			}						 \
		      else if (_FP_FRAC_ZEROP_##wc(R))			 \
			R##_s = (FP_ROUNDMODE == FP_RND_MINF);		 \
		      goto sub_done;					 \
		    }							 \
		}							 \
	      else							 \
		{							 \
		  /* X and Y are NaN or Inf, of opposite signs.  */	 \
		  _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, X);			 \
		  _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, Y);			 \
		  R##_e = _FP_EXPMAX_##fs;				 \
		  if (_FP_FRAC_ZEROP_##wc(X))				 \
		    {							 \
		      if (_FP_FRAC_ZEROP_##wc(Y))			 \
			{						 \
			  /* Inf - Inf.  */				 \
			  R##_s = _FP_NANSIGN_##fs;			 \
			  _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs);	 \
			  _FP_FRAC_SLL_##wc(R, _FP_WORKBITS);		 \
			  FP_SET_EXCEPTION(FP_EX_INVALID);		 \
			}						 \
		      else						 \
			{						 \
			  /* Inf - NaN.  */				 \
			  R##_s = Y##_s;				 \
			  _FP_FRAC_COPY_##wc(R, Y);			 \
			}						 \
		    }							 \
		  else							 \
		    {							 \
		      if (_FP_FRAC_ZEROP_##wc(Y))			 \
			{						 \
			  /* NaN - Inf.  */				 \
			  R##_s = X##_s;				 \
			  _FP_FRAC_COPY_##wc(R, X);			 \
			}						 \
		      else						 \
			{						 \
			  /* NaN - NaN.  */				 \
			  _FP_CHOOSENAN_SEMIRAW(fs, wc, R, X, Y, OP);	 \
			}						 \
		    }							 \
		  goto sub_done;					 \
		}							 \
	    }								 \
	  /* The exponents of X and Y, both normal, are equal.  The	 \
	     implicit MSBs cancel.  */					 \
	  R##_e = X##_e;						 \
	  _FP_FRAC_SUB_##wc(R, X, Y);					 \
	  R##_s = X##_s;						 \
	  if (_FP_FRAC_HIGH_##fs(R) & _FP_IMPLBIT_SH_##fs)		 \
	    {								 \
	      /* |X| < |Y|, negate result.  */				 \
	      _FP_FRAC_SUB_##wc(R, Y, X);				 \
	      R##_s = Y##_s;						 \
	    }								 \
	  else if (_FP_FRAC_ZEROP_##wc(R))				 \
	    {								 \
	      R##_e = 0;						 \
	      R##_s = (FP_ROUNDMODE == FP_RND_MINF);			 \
	      goto sub_done;						 \
	    }								 \
	  goto norm;							 \
	}								 \
    sub3:								 \
      if (_FP_FRAC_HIGH_##fs(R) & _FP_IMPLBIT_SH_##fs)			 \
	{								 \
	  int diff;							 \
	  /* Carry into most significant bit of larger one of X and Y,	 \
	     canceling it; renormalize.  */				 \
	  _FP_FRAC_HIGH_##fs(R) &= _FP_IMPLBIT_SH_##fs - 1;		 \
	norm:								 \
	  _FP_FRAC_CLZ_##wc(diff, R);					 \
	  diff -= _FP_WFRACXBITS_##fs;					 \
	  _FP_FRAC_SLL_##wc(R, diff);					 \
	  if (R##_e <= diff)						 \
	    {								 \
	      /* R is denormalized.  */					 \
	      diff = diff - R##_e + 1;					 \
	      _FP_FRAC_SRS_##wc(R, diff, _FP_WFRACBITS_##fs);		 \
	      R##_e = 0;						 \
	    }								 \
	  else								 \
	    {								 \
	      R##_e -= diff;						 \
	      _FP_FRAC_HIGH_##fs(R) &= ~(_FP_W_TYPE)_FP_IMPLBIT_SH_##fs; \
	    }								 \
	}								 \
    sub_done: ;								 \
    }									 \
} while (0)

#define _FP_ADD(fs, wc, R, X, Y) _FP_ADD_INTERNAL(fs, wc, R, X, Y, '+')
#define _FP_SUB(fs, wc, R, X, Y)					    \
  do {									    \
    if (!(Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(Y))) Y##_s ^= 1; \
    _FP_ADD_INTERNAL(fs, wc, R, X, Y, '-');				    \
  } while (0)


/*
 * Main negation routine.  FIXME -- when we care about setting exception
 * bits reliably, this will not do.  We should examine all of the fp classes.
 */

#define _FP_NEG(fs, wc, R, X)		\
  do {					\
    _FP_FRAC_COPY_##wc(R, X);		\
    R##_c = X##_c;			\
    R##_e = X##_e;			\
    R##_s = 1 ^ X##_s;			\
  } while (0)


/*
 * Main multiplication routine.  The input values should be cooked.
 */

#define _FP_MUL(fs, wc, R, X, Y)			\
do {							\
  R##_s = X##_s ^ Y##_s;				\
  switch (_FP_CLS_COMBINE(X##_c, Y##_c))		\
  {							\
  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL):	\
    R##_c = FP_CLS_NORMAL;				\
    R##_e = X##_e + Y##_e + 1;				\
							\
    _FP_MUL_MEAT_##fs(R,X,Y);				\
							\
    if (_FP_FRAC_OVERP_##wc(fs, R))			\
      _FP_FRAC_SRS_##wc(R, 1, _FP_WFRACBITS_##fs);	\
    else						\
      R##_e--;						\
    break;						\
							\
  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN):		\
    _FP_CHOOSENAN(fs, wc, R, X, Y, '*');		\
    break;						\
							\
  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL):	\
  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF):		\
  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO):		\
    R##_s = X##_s;					\
							\
  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF):		\
  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL):	\
  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL):	\
  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO):	\
    _FP_FRAC_COPY_##wc(R, X);				\
    R##_c = X##_c;					\
    break;						\
							\
  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN):	\
  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN):		\
  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN):		\
    R##_s = Y##_s;					\
							\
  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF):	\
  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO):	\
    _FP_FRAC_COPY_##wc(R, Y);				\
    R##_c = Y##_c;					\
    break;						\
							\
  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO):		\
  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF):		\
    R##_s = _FP_NANSIGN_##fs;				\
    R##_c = FP_CLS_NAN;					\
    _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs);		\
    FP_SET_EXCEPTION(FP_EX_INVALID);			\
    break;						\
							\
  default:						\
    abort();						\
  }							\
} while (0)


/*
 * Main division routine.  The input values should be cooked.
 */

#define _FP_DIV(fs, wc, R, X, Y)			\
do {							\
  R##_s = X##_s ^ Y##_s;				\
  switch (_FP_CLS_COMBINE(X##_c, Y##_c))		\
  {							\
  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL):	\
    R##_c = FP_CLS_NORMAL;				\
    R##_e = X##_e - Y##_e;				\
							\
    _FP_DIV_MEAT_##fs(R,X,Y);				\
    break;						\
							\
  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN):		\
    _FP_CHOOSENAN(fs, wc, R, X, Y, '/');		\
    break;						\
							\
  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL):	\
  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF):		\
  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO):		\
    R##_s = X##_s;					\
    _FP_FRAC_COPY_##wc(R, X);				\
    R##_c = X##_c;					\
    break;						\
							\
  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN):	\
  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN):		\
  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN):		\
    R##_s = Y##_s;					\
    _FP_FRAC_COPY_##wc(R, Y);				\
    R##_c = Y##_c;					\
    break;						\
							\
  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF):	\
  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF):		\
  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL):	\
    R##_c = FP_CLS_ZERO;				\
    break;						\
							\
  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO):	\
    FP_SET_EXCEPTION(FP_EX_DIVZERO);			\
  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO):		\
  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL):	\
    R##_c = FP_CLS_INF;					\
    break;						\
							\
  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF):		\
  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO):	\
    R##_s = _FP_NANSIGN_##fs;				\
    R##_c = FP_CLS_NAN;					\
    _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs);		\
    FP_SET_EXCEPTION(FP_EX_INVALID);			\
    break;						\
							\
  default:						\
    abort();						\
  }							\
} while (0)


/*
 * Main differential comparison routine.  The inputs should be raw not
 * cooked.  The return is -1,0,1 for normal values, 2 otherwise.
 */

#define _FP_CMP(fs, wc, ret, X, Y, un)					\
  do {									\
    /* NANs are unordered */						\
    if ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(X))		\
	|| (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(Y)))	\
      {									\
	ret = un;							\
      }									\
    else								\
      {									\
	int __is_zero_x;						\
	int __is_zero_y;						\
									\
	__is_zero_x = (!X##_e && _FP_FRAC_ZEROP_##wc(X)) ? 1 : 0;	\
	__is_zero_y = (!Y##_e && _FP_FRAC_ZEROP_##wc(Y)) ? 1 : 0;	\
									\
	if (__is_zero_x && __is_zero_y)					\
		ret = 0;						\
	else if (__is_zero_x)						\
		ret = Y##_s ? 1 : -1;					\
	else if (__is_zero_y)						\
		ret = X##_s ? -1 : 1;					\
	else if (X##_s != Y##_s)					\
	  ret = X##_s ? -1 : 1;						\
	else if (X##_e > Y##_e)						\
	  ret = X##_s ? -1 : 1;						\
	else if (X##_e < Y##_e)						\
	  ret = X##_s ? 1 : -1;						\
	else if (_FP_FRAC_GT_##wc(X, Y))				\
	  ret = X##_s ? -1 : 1;						\
	else if (_FP_FRAC_GT_##wc(Y, X))				\
	  ret = X##_s ? 1 : -1;						\
	else								\
	  ret = 0;							\
      }									\
  } while (0)


/* Simplification for strict equality.  */

#define _FP_CMP_EQ(fs, wc, ret, X, Y)					    \
  do {									    \
    /* NANs are unordered */						    \
    if ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(X))		    \
	|| (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(Y)))	    \
      {									    \
	ret = 1;							    \
      }									    \
    else								    \
      {									    \
	ret = !(X##_e == Y##_e						    \
		&& _FP_FRAC_EQ_##wc(X, Y)				    \
		&& (X##_s == Y##_s || (!X##_e && _FP_FRAC_ZEROP_##wc(X)))); \
      }									    \
  } while (0)

/* Version to test unordered.  */

#define _FP_CMP_UNORD(fs, wc, ret, X, Y)				\
  do {									\
    ret = ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(X))	\
	   || (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(Y)));	\
  } while (0)

/*
 * Main square root routine.  The input value should be cooked.
 */

#define _FP_SQRT(fs, wc, R, X)						\
do {									\
    _FP_FRAC_DECL_##wc(T); _FP_FRAC_DECL_##wc(S);			\
    _FP_W_TYPE q;							\
    switch (X##_c)							\
    {									\
    case FP_CLS_NAN:							\
	_FP_FRAC_COPY_##wc(R, X);					\
	R##_s = X##_s;							\
    	R##_c = FP_CLS_NAN;						\
    	break;								\
    case FP_CLS_INF:							\
    	if (X##_s)							\
    	  {								\
    	    R##_s = _FP_NANSIGN_##fs;					\
	    R##_c = FP_CLS_NAN; /* NAN */				\
	    _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs);			\
	    FP_SET_EXCEPTION(FP_EX_INVALID);				\
    	  }								\
    	else								\
    	  {								\
    	    R##_s = 0;							\
    	    R##_c = FP_CLS_INF; /* sqrt(+inf) = +inf */			\
    	  }								\
    	break;								\
    case FP_CLS_ZERO:							\
	R##_s = X##_s;							\
	R##_c = FP_CLS_ZERO; /* sqrt(+-0) = +-0 */			\
	break;								\
    case FP_CLS_NORMAL:							\
    	R##_s = 0;							\
        if (X##_s)							\
          {								\
	    R##_c = FP_CLS_NAN; /* sNAN */				\
	    R##_s = _FP_NANSIGN_##fs;					\
	    _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs);			\
	    FP_SET_EXCEPTION(FP_EX_INVALID);				\
	    break;							\
          }								\
    	R##_c = FP_CLS_NORMAL;						\
        if (X##_e & 1)							\
          _FP_FRAC_SLL_##wc(X, 1);					\
        R##_e = X##_e >> 1;						\
        _FP_FRAC_SET_##wc(S, _FP_ZEROFRAC_##wc);			\
        _FP_FRAC_SET_##wc(R, _FP_ZEROFRAC_##wc);			\
        q = _FP_OVERFLOW_##fs >> 1;					\
        _FP_SQRT_MEAT_##wc(R, S, T, X, q);				\
    }									\
  } while (0)

/*
 * Convert from FP to integer.  Input is raw.
 */

/* RSIGNED can have following values:
 * 0:  the number is required to be 0..(2^rsize)-1, if not, NV is set plus
 *     the result is either 0 or (2^rsize)-1 depending on the sign in such
 *     case.
 * 1:  the number is required to be -(2^(rsize-1))..(2^(rsize-1))-1, if not,
 *     NV is set plus the result is either -(2^(rsize-1)) or (2^(rsize-1))-1
 *     depending on the sign in such case.
 * -1: the number is required to be -(2^(rsize-1))..(2^rsize)-1, if not, NV is
 *     set plus the result is either -(2^(rsize-1)) or (2^(rsize-1))-1
 *     depending on the sign in such case.
 */
#define _FP_TO_INT(fs, wc, r, X, rsize, rsigned)			\
do {									\
  if (X##_e < _FP_EXPBIAS_##fs)						\
    {									\
      r = 0;								\
      if (X##_e == 0)							\
	{								\
	  if (!_FP_FRAC_ZEROP_##wc(X))					\
	    {								\
	      FP_SET_EXCEPTION(FP_EX_INEXACT);				\
	      FP_SET_EXCEPTION(FP_EX_DENORM);				\
	    }								\
	}								\
      else								\
	FP_SET_EXCEPTION(FP_EX_INEXACT);				\
    }									\
  else if (X##_e >= _FP_EXPBIAS_##fs + rsize - (rsigned > 0 || X##_s)	\
	   || (!rsigned && X##_s))					\
    {									\
      /* Overflow or converting to the most negative integer.  */	\
      if (rsigned)							\
	{								\
	  r = 1;							\
	  r <<= rsize - 1;						\
	  r -= 1 - X##_s;						\
	} else {							\
	  r = 0;							\
	  if (X##_s)							\
	    r = ~r;							\
	}								\
									\
      if (rsigned && X##_s && X##_e == _FP_EXPBIAS_##fs + rsize - 1)	\
	{								\
	  /* Possibly converting to most negative integer; check the	\
	     mantissa.  */						\
	  int inexact = 0;						\
	  (void)((_FP_FRACBITS_##fs > rsize)				\
		 ? ({ _FP_FRAC_SRST_##wc(X, inexact,			\
					 _FP_FRACBITS_##fs - rsize,	\
					 _FP_FRACBITS_##fs); 0; })	\
		 : 0);							\
	  if (!_FP_FRAC_ZEROP_##wc(X))					\
	    FP_SET_EXCEPTION(FP_EX_INVALID);				\
	  else if (inexact)						\
	    FP_SET_EXCEPTION(FP_EX_INEXACT);				\
	}								\
      else								\
	FP_SET_EXCEPTION(FP_EX_INVALID);				\
    }									\
  else									\
    {									\
      _FP_FRAC_HIGH_RAW_##fs(X) |= _FP_IMPLBIT_##fs;			\
      if (X##_e >= _FP_EXPBIAS_##fs + _FP_FRACBITS_##fs - 1)		\
	{								\
	  _FP_FRAC_ASSEMBLE_##wc(r, X, rsize);				\
	  r <<= X##_e - _FP_EXPBIAS_##fs - _FP_FRACBITS_##fs + 1;	\
	}								\
      else								\
	{								\
	  int inexact;							\
	  _FP_FRAC_SRST_##wc(X, inexact,				\
			    (_FP_FRACBITS_##fs + _FP_EXPBIAS_##fs - 1	\
			     - X##_e),					\
			    _FP_FRACBITS_##fs);				\
	  if (inexact)							\
	    FP_SET_EXCEPTION(FP_EX_INEXACT);				\
	  _FP_FRAC_ASSEMBLE_##wc(r, X, rsize);				\
	}								\
      if (rsigned && X##_s)						\
	r = -r;								\
    }									\
} while (0)

/* Convert integer to fp.  Output is raw.  RTYPE is unsigned even if
   input is signed.  */
#define _FP_FROM_INT(fs, wc, X, r, rsize, rtype)			     \
  do {									     \
    if (r)								     \
      {									     \
	rtype ur_;							     \
									     \
	if ((X##_s = (r < 0)))						     \
	  r = -(rtype)r;						     \
									     \
	ur_ = (rtype) r;						     \
	(void)((rsize <= _FP_W_TYPE_SIZE)				     \
	       ? ({							     \
		    int lz_;						     \
		    __FP_CLZ(lz_, (_FP_W_TYPE)ur_);			     \
		    X##_e = _FP_EXPBIAS_##fs + _FP_W_TYPE_SIZE - 1 - lz_;    \
		  })							     \
	       : ((rsize <= 2 * _FP_W_TYPE_SIZE)			     \
		  ? ({							     \
		       int lz_;						     \
		       __FP_CLZ_2(lz_, (_FP_W_TYPE)(ur_ >> _FP_W_TYPE_SIZE), \
				  (_FP_W_TYPE)ur_);			     \
		       X##_e = (_FP_EXPBIAS_##fs + 2 * _FP_W_TYPE_SIZE - 1   \
				- lz_);					     \
		     })							     \
		  : (abort(), 0)));					     \
									     \
	if (rsize - 1 + _FP_EXPBIAS_##fs >= _FP_EXPMAX_##fs		     \
	    && X##_e >= _FP_EXPMAX_##fs)				     \
	  {								     \
	    /* Exponent too big; overflow to infinity.  (May also	     \
	       happen after rounding below.)  */			     \
	    _FP_OVERFLOW_SEMIRAW(fs, wc, X);				     \
	    goto pack_semiraw;						     \
	  }								     \
									     \
	if (rsize <= _FP_FRACBITS_##fs					     \
	    || X##_e < _FP_EXPBIAS_##fs + _FP_FRACBITS_##fs)		     \
	  {								     \
	    /* Exactly representable; shift left.  */			     \
	    _FP_FRAC_DISASSEMBLE_##wc(X, ur_, rsize);			     \
	    _FP_FRAC_SLL_##wc(X, (_FP_EXPBIAS_##fs			     \
				  + _FP_FRACBITS_##fs - 1 - X##_e));	     \
	  }								     \
	else								     \
	  {								     \
	    /* More bits in integer than in floating type; need to	     \
	       round.  */						     \
	    if (_FP_EXPBIAS_##fs + _FP_WFRACBITS_##fs - 1 < X##_e)	     \
	      ur_ = ((ur_ >> (X##_e - _FP_EXPBIAS_##fs			     \
			      - _FP_WFRACBITS_##fs + 1))		     \
		     | ((ur_ << (rsize - (X##_e - _FP_EXPBIAS_##fs	     \
					  - _FP_WFRACBITS_##fs + 1)))	     \
			!= 0));						     \
	    _FP_FRAC_DISASSEMBLE_##wc(X, ur_, rsize);			     \
	    if ((_FP_EXPBIAS_##fs + _FP_WFRACBITS_##fs - 1 - X##_e) > 0)     \
	      _FP_FRAC_SLL_##wc(X, (_FP_EXPBIAS_##fs			     \
				    + _FP_WFRACBITS_##fs - 1 - X##_e));	     \
	    _FP_FRAC_HIGH_##fs(X) &= ~(_FP_W_TYPE)_FP_IMPLBIT_SH_##fs;	     \
	  pack_semiraw:							     \
	    _FP_PACK_SEMIRAW(fs, wc, X);				     \
	  }								     \
      }									     \
    else								     \
      {									     \
	X##_s = 0;							     \
	X##_e = 0;							     \
	_FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc);			     \
      }									     \
  } while (0)


/* Extend from a narrower floating-point format to a wider one.  Input
   and output are raw.  */
#define FP_EXTEND(dfs,sfs,dwc,swc,D,S)					 \
do {									 \
  if (_FP_FRACBITS_##dfs < _FP_FRACBITS_##sfs				 \
      || (_FP_EXPMAX_##dfs - _FP_EXPBIAS_##dfs				 \
	  < _FP_EXPMAX_##sfs - _FP_EXPBIAS_##sfs)			 \
      || (_FP_EXPBIAS_##dfs < _FP_EXPBIAS_##sfs + _FP_FRACBITS_##sfs - 1 \
	  && _FP_EXPBIAS_##dfs != _FP_EXPBIAS_##sfs))			 \
    abort();								 \
  D##_s = S##_s;							 \
  _FP_FRAC_COPY_##dwc##_##swc(D, S);					 \
  if (_FP_EXP_NORMAL(sfs, swc, S))					 \
    {									 \
      D##_e = S##_e + _FP_EXPBIAS_##dfs - _FP_EXPBIAS_##sfs;		 \
      _FP_FRAC_SLL_##dwc(D, (_FP_FRACBITS_##dfs - _FP_FRACBITS_##sfs));	 \
    }									 \
  else									 \
    {									 \
      if (S##_e == 0)							 \
	{								 \
	  if (_FP_FRAC_ZEROP_##swc(S))					 \
	    D##_e = 0;							 \
	  else if (_FP_EXPBIAS_##dfs					 \
		   < _FP_EXPBIAS_##sfs + _FP_FRACBITS_##sfs - 1)	 \
	    {								 \
	      FP_SET_EXCEPTION(FP_EX_DENORM);				 \
	      _FP_FRAC_SLL_##dwc(D, (_FP_FRACBITS_##dfs			 \
				     - _FP_FRACBITS_##sfs));		 \
	      D##_e = 0;						 \
	    }								 \
	  else								 \
	    {								 \
	      int _lz;							 \
	      FP_SET_EXCEPTION(FP_EX_DENORM);				 \
	      _FP_FRAC_CLZ_##swc(_lz, S);				 \
	      _FP_FRAC_SLL_##dwc(D,					 \
				 _lz + _FP_FRACBITS_##dfs		 \
				 - _FP_FRACTBITS_##sfs);		 \
	      D##_e = (_FP_EXPBIAS_##dfs - _FP_EXPBIAS_##sfs + 1	 \
		       + _FP_FRACXBITS_##sfs - _lz);			 \
	    }								 \
	}								 \
      else								 \
	{								 \
	  D##_e = _FP_EXPMAX_##dfs;					 \
	  if (!_FP_FRAC_ZEROP_##swc(S))					 \
	    {								 \
	      if (!(_FP_FRAC_HIGH_RAW_##sfs(S) & _FP_QNANBIT_##sfs))	 \
		FP_SET_EXCEPTION(FP_EX_INVALID);			 \
	      _FP_FRAC_SLL_##dwc(D, (_FP_FRACBITS_##dfs			 \
				     - _FP_FRACBITS_##sfs));		 \
	    }								 \
	}								 \
    }									 \
} while (0)

/* Truncate from a wider floating-point format to a narrower one.
   Input and output are semi-raw.  */
#define FP_TRUNC(dfs,sfs,dwc,swc,D,S)					     \
do {									     \
  if (_FP_FRACBITS_##sfs < _FP_FRACBITS_##dfs				     \
      || (_FP_EXPBIAS_##sfs < _FP_EXPBIAS_##dfs + _FP_FRACBITS_##dfs - 1     \
	  && _FP_EXPBIAS_##sfs != _FP_EXPBIAS_##dfs))			     \
    abort();								     \
  D##_s = S##_s;							     \
  if (_FP_EXP_NORMAL(sfs, swc, S))					     \
    {									     \
      D##_e = S##_e + _FP_EXPBIAS_##dfs - _FP_EXPBIAS_##sfs;		     \
      if (D##_e >= _FP_EXPMAX_##dfs)					     \
	_FP_OVERFLOW_SEMIRAW(dfs, dwc, D);				     \
      else								     \
	{								     \
	  if (D##_e <= 0)						     \
	    {								     \
	      if (D##_e < 1 - _FP_FRACBITS_##dfs)			     \
		{							     \
		  _FP_FRAC_SET_##swc(S, _FP_ZEROFRAC_##swc);		     \
		  _FP_FRAC_LOW_##swc(S) |= 1;				     \
		}							     \
	      else							     \
		{							     \
		  _FP_FRAC_HIGH_##sfs(S) |= _FP_IMPLBIT_SH_##sfs;	     \
		  _FP_FRAC_SRS_##swc(S, (_FP_WFRACBITS_##sfs		     \
					 - _FP_WFRACBITS_##dfs + 1 - D##_e), \
				     _FP_WFRACBITS_##sfs);		     \
		}							     \
	      D##_e = 0;						     \
	    }								     \
	  else								     \
	    _FP_FRAC_SRS_##swc(S, (_FP_WFRACBITS_##sfs			     \
				   - _FP_WFRACBITS_##dfs),		     \
			       _FP_WFRACBITS_##sfs);			     \
	  _FP_FRAC_COPY_##dwc##_##swc(D, S);				     \
	}								     \
    }									     \
  else									     \
    {									     \
      if (S##_e == 0)							     \
	{								     \
	  D##_e = 0;							     \
	  if (_FP_FRAC_ZEROP_##swc(S))					     \
	    _FP_FRAC_SET_##dwc(D, _FP_ZEROFRAC_##dwc);			     \
	  else								     \
	    {								     \
	      FP_SET_EXCEPTION(FP_EX_DENORM);				     \
	      if (_FP_EXPBIAS_##sfs					     \
		  < _FP_EXPBIAS_##dfs + _FP_FRACBITS_##dfs - 1)		     \
		{							     \
		  _FP_FRAC_SRS_##swc(S, (_FP_WFRACBITS_##sfs		     \
					 - _FP_WFRACBITS_##dfs),	     \
				     _FP_WFRACBITS_##sfs);		     \
		  _FP_FRAC_COPY_##dwc##_##swc(D, S);			     \
		}							     \
	      else							     \
		{							     \
		  _FP_FRAC_SET_##dwc(D, _FP_ZEROFRAC_##dwc);		     \
		  _FP_FRAC_LOW_##dwc(D) |= 1;				     \
		}							     \
	    }								     \
	}								     \
      else								     \
	{								     \
	  D##_e = _FP_EXPMAX_##dfs;					     \
	  if (_FP_FRAC_ZEROP_##swc(S))					     \
	    _FP_FRAC_SET_##dwc(D, _FP_ZEROFRAC_##dwc);			     \
	  else								     \
	    {								     \
	      _FP_CHECK_SIGNAN_SEMIRAW(sfs, swc, S);			     \
	      _FP_FRAC_SRL_##swc(S, (_FP_WFRACBITS_##sfs		     \
				     - _FP_WFRACBITS_##dfs));		     \
	      _FP_FRAC_COPY_##dwc##_##swc(D, S);			     \
	      /* Semi-raw NaN must have all workbits cleared.  */	     \
	      _FP_FRAC_LOW_##dwc(D)					     \
		&= ~(_FP_W_TYPE) ((1 << _FP_WORKBITS) - 1);		     \
	      _FP_FRAC_HIGH_##dfs(D) |= _FP_QNANBIT_SH_##dfs;		     \
	    }								     \
	}								     \
    }									     \
} while (0)

/*
 * Helper primitives.
 */

/* Count leading zeros in a word.  */

#ifndef __FP_CLZ
/* GCC 3.4 and later provide the builtins for us.  */
#define __FP_CLZ(r, x)							      \
  do {									      \
    if (sizeof (_FP_W_TYPE) == sizeof (unsigned int))			      \
      r = __builtin_clz (x);						      \
    else if (sizeof (_FP_W_TYPE) == sizeof (unsigned long))		      \
      r = __builtin_clzl (x);						      \
    else if (sizeof (_FP_W_TYPE) == sizeof (unsigned long long))	      \
      r = __builtin_clzll (x);						      \
    else								      \
      abort ();								      \
  } while (0)
#endif /* ndef __FP_CLZ */

#define _FP_DIV_HELP_imm(q, r, n, d)		\
  do {						\
    q = n / d, r = n % d;			\
  } while (0)


/* A restoring bit-by-bit division primitive.  */

#define _FP_DIV_MEAT_N_loop(fs, wc, R, X, Y)				\
  do {									\
    int count = _FP_WFRACBITS_##fs;					\
    _FP_FRAC_DECL_##wc (u);						\
    _FP_FRAC_DECL_##wc (v);						\
    _FP_FRAC_COPY_##wc (u, X);						\
    _FP_FRAC_COPY_##wc (v, Y);						\
    _FP_FRAC_SET_##wc (R, _FP_ZEROFRAC_##wc);				\
    /* Normalize U and V.  */						\
    _FP_FRAC_SLL_##wc (u, _FP_WFRACXBITS_##fs);				\
    _FP_FRAC_SLL_##wc (v, _FP_WFRACXBITS_##fs);				\
    /* First round.  Since the operands are normalized, either the	\
       first or second bit will be set in the fraction.  Produce a	\
       normalized result by checking which and adjusting the loop	\
       count and exponent accordingly.  */				\
    if (_FP_FRAC_GE_1 (u, v))						\
      {									\
	_FP_FRAC_SUB_##wc (u, u, v);					\
	_FP_FRAC_LOW_##wc (R) |= 1;					\
	count--;							\
      }									\
    else								\
      R##_e--;								\
    /* Subsequent rounds.  */						\
    do {								\
      int msb = (_FP_WS_TYPE) _FP_FRAC_HIGH_##wc (u) < 0;		\
      _FP_FRAC_SLL_##wc (u, 1);						\
      _FP_FRAC_SLL_##wc (R, 1);						\
      if (msb || _FP_FRAC_GE_1 (u, v))					\
	{								\
	  _FP_FRAC_SUB_##wc (u, u, v);					\
	  _FP_FRAC_LOW_##wc (R) |= 1;					\
	}								\
    } while (--count > 0);						\
    /* If there's anything left in U, the result is inexact.  */	\
    _FP_FRAC_LOW_##wc (R) |= !_FP_FRAC_ZEROP_##wc (u);			\
  } while (0)

#define _FP_DIV_MEAT_1_loop(fs, R, X, Y)  _FP_DIV_MEAT_N_loop (fs, 1, R, X, Y)
#define _FP_DIV_MEAT_2_loop(fs, R, X, Y)  _FP_DIV_MEAT_N_loop (fs, 2, R, X, Y)
#define _FP_DIV_MEAT_4_loop(fs, R, X, Y)  _FP_DIV_MEAT_N_loop (fs, 4, R, X, Y)


/* Sigh.  Silly things longlong.h needs.  */
#define UWtype		_FP_W_TYPE
#define W_TYPE_SIZE	_FP_W_TYPE_SIZE

typedef int QItype __attribute__((mode(QI)));
typedef int SItype __attribute__((mode(SI)));
typedef int DItype __attribute__((mode(DI)));
typedef unsigned int UQItype __attribute__((mode(QI)));
typedef unsigned int USItype __attribute__((mode(SI)));
typedef unsigned int UDItype __attribute__((mode(DI)));
#if _FP_W_TYPE_SIZE == 32
typedef unsigned int UHWtype __attribute__((mode(HI)));
#elif _FP_W_TYPE_SIZE == 64
typedef USItype UHWtype;
#endif

#ifndef CMPtype
#define CMPtype		int
#endif

#define SI_BITS		(__CHAR_BIT__ * (int)sizeof(SItype))
#define DI_BITS		(__CHAR_BIT__ * (int)sizeof(DItype))

//#ifndef umul_ppmm
//#ifdef _LIBC
//#include <stdlib/longlong.h>
//#else
//#include "longlong.h"
//#endif
//#endif

#define __BITS4 (W_TYPE_SIZE / 4)
#define __ll_B ((UWtype) 1 << (W_TYPE_SIZE / 2))
#define __ll_lowpart(t) ((UWtype) (t) & (__ll_B - 1))
#define __ll_highpart(t) ((UWtype) (t) >> (W_TYPE_SIZE / 2))

#ifndef W_TYPE_SIZE
#define W_TYPE_SIZE 32
#define UWtype      USItype
#define UHWtype     USItype
#define UDWtype     UDItype
#endif

/* Define auxiliary asm macros.

   1) umul_ppmm(high_prod, low_prod, multipler, multiplicand) multiplies two
   UWtype integers MULTIPLER and MULTIPLICAND, and generates a two UWtype
   word product in HIGH_PROD and LOW_PROD.

   2) __umulsidi3(a,b) multiplies two UWtype integers A and B, and returns a
   UDWtype product.  This is just a variant of umul_ppmm.

   3) udiv_qrnnd(quotient, remainder, high_numerator, low_numerator,
   denominator) divides a UDWtype, composed by the UWtype integers
   HIGH_NUMERATOR and LOW_NUMERATOR, by DENOMINATOR and places the quotient
   in QUOTIENT and the remainder in REMAINDER.  HIGH_NUMERATOR must be less
   than DENOMINATOR for correct operation.  If, in addition, the most
   significant bit of DENOMINATOR must be 1, then the pre-processor symbol
   UDIV_NEEDS_NORMALIZATION is defined to 1.

   4) sdiv_qrnnd(quotient, remainder, high_numerator, low_numerator,
   denominator).  Like udiv_qrnnd but the numbers are signed.  The quotient
   is rounded towards 0.

   5) count_leading_zeros(count, x) counts the number of zero-bits from the
   msb to the first nonzero bit in the UWtype X.  This is the number of
   steps X needs to be shifted left to set the msb.  Undefined for X == 0,
   unless the symbol COUNT_LEADING_ZEROS_0 is defined to some value.

   6) count_trailing_zeros(count, x) like count_leading_zeros, but counts
   from the least significant end.

   7) add_ssaaaa(high_sum, low_sum, high_addend_1, low_addend_1,
   high_addend_2, low_addend_2) adds two UWtype integers, composed by
   HIGH_ADDEND_1 and LOW_ADDEND_1, and HIGH_ADDEND_2 and LOW_ADDEND_2
   respectively.  The result is placed in HIGH_SUM and LOW_SUM.  Overflow
   (i.e. carry out) is not stored anywhere, and is lost.

   8) sub_ddmmss(high_difference, low_difference, high_minuend, low_minuend,
   high_subtrahend, low_subtrahend) subtracts two two-word UWtype integers,
   composed by HIGH_MINUEND_1 and LOW_MINUEND_1, and HIGH_SUBTRAHEND_2 and
   LOW_SUBTRAHEND_2 respectively.  The result is placed in HIGH_DIFFERENCE
   and LOW_DIFFERENCE.  Overflow (i.e. carry out) is not stored anywhere,
   and is lost.

   If any of these macros are left undefined for a particular CPU,
   C macros are used.  */

/* The CPUs come in alphabetical order below.

   Please add support for more CPUs here, or improve the current support
   for the CPUs below!
   (E.g. WE32100, IBM360.)  */

#if defined (__GNUC__) && !defined (NO_ASM)

/* We sometimes need to clobber "cc" with gcc2, but that would not be
   understood by gcc1.  Use cpp to avoid major code duplication.  */
#if __GNUC__ < 2
#define __CLOBBER_CC
#define __AND_CLOBBER_CC
#else /* __GNUC__ >= 2 */
#define __CLOBBER_CC : "cc"
#define __AND_CLOBBER_CC , "cc"
#endif /* __GNUC__ < 2 */

#if defined (__alpha) && W_TYPE_SIZE == 64
#define umul_ppmm(ph, pl, m0, m1) \
  do {                                  \
    UDItype __m0 = (m0), __m1 = (m1);                   \
    __asm__ ("umulh %r1,%2,%0"                      \
         : "=r" ((UDItype) ph)                  \
         : "%rJ" (__m0),                        \
           "rI" (__m1));                        \
    (pl) = __m0 * __m1;                         \
  } while (0)
#define UMUL_TIME 46
#ifndef LONGLONG_STANDALONE
#define udiv_qrnnd(q, r, n1, n0, d) \
  do { UDItype __r;                         \
    (q) = __udiv_qrnnd (&__r, (n1), (n0), (d));             \
    (r) = __r;                              \
  } while (0)
extern UDItype __udiv_qrnnd (UDItype *, UDItype, UDItype, UDItype);
#define UDIV_TIME 220
#endif /* LONGLONG_STANDALONE */
#ifdef __alpha_cix__
#define count_leading_zeros(COUNT,X) \
  __asm__("ctlz %1,%0" : "=r"(COUNT) : "r"(X))
#define count_trailing_zeros(COUNT,X) \
  __asm__("cttz %1,%0" : "=r"(COUNT) : "r"(X))
#define COUNT_LEADING_ZEROS_0 64
#else
extern const UQItype __clz_tab[];
#define count_leading_zeros(COUNT,X) \
  do {                                  \
    UDItype __xr = (X), __t, __a;                   \
    __asm__("cmpbge $31,%1,%0" : "=r"(__t) : "r"(__xr));        \
    __a = __clz_tab[__t ^ 0xff] - 1;                    \
    __asm__("extbl %1,%2,%0" : "=r"(__t) : "r"(__xr), "r"(__a));    \
    (COUNT) = 64 - (__clz_tab[__t] + __a*8);                \
  } while (0)
#define count_trailing_zeros(COUNT,X) \
  do {                                  \
    UDItype __xr = (X), __t, __a;                   \
    __asm__("cmpbge $31,%1,%0" : "=r"(__t) : "r"(__xr));        \
    __t = ~__t & -~__t;                         \
    __a = ((__t & 0xCC) != 0) * 2;                  \
    __a += ((__t & 0xF0) != 0) * 4;                 \
    __a += ((__t & 0xAA) != 0);                     \
    __asm__("extbl %1,%2,%0" : "=r"(__t) : "r"(__xr), "r"(__a));    \
    __a <<= 3;                              \
    __t &= -__t;                            \
    __a += ((__t & 0xCC) != 0) * 2;                 \
    __a += ((__t & 0xF0) != 0) * 4;                 \
    __a += ((__t & 0xAA) != 0);                     \
    (COUNT) = __a;                          \
  } while (0)
#endif /* __alpha_cix__ */
#endif /* __alpha */

#if defined (__arc__) && W_TYPE_SIZE == 32
#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
  __asm__ ("add.f   %1, %4, %5\n\tadc   %0, %2, %3"     \
       : "=r" ((USItype) (sh)),                 \
         "=&r" ((USItype) (sl))                 \
       : "%r" ((USItype) (ah)),                 \
         "rIJ" ((USItype) (bh)),                    \
         "%r" ((USItype) (al)),                 \
         "rIJ" ((USItype) (bl)))
#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
  __asm__ ("sub.f   %1, %4, %5\n\tsbc   %0, %2, %3"     \
       : "=r" ((USItype) (sh)),                 \
         "=&r" ((USItype) (sl))                 \
       : "r" ((USItype) (ah)),                  \
         "rIJ" ((USItype) (bh)),                    \
         "r" ((USItype) (al)),                  \
         "rIJ" ((USItype) (bl)))
/* Call libgcc routine.  */
#define umul_ppmm(w1, w0, u, v) \
do {                                    \
  DWunion __w;                              \
  __w.ll = __umulsidi3 (u, v);                      \
  w1 = __w.s.high;                          \
  w0 = __w.s.low;                           \
} while (0)
#define __umulsidi3 __umulsidi3
UDItype __umulsidi3 (USItype, USItype);
#endif

#if defined (__arm__) && W_TYPE_SIZE == 32
#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
  __asm__ ("adds    %1, %4, %5\n\tadc   %0, %2, %3"     \
       : "=r" ((USItype) (sh)),                 \
         "=&r" ((USItype) (sl))                 \
       : "%r" ((USItype) (ah)),                 \
         "rI" ((USItype) (bh)),                 \
         "%r" ((USItype) (al)),                 \
         "rI" ((USItype) (bl)))
#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
  __asm__ ("subs    %1, %4, %5\n\tsbc   %0, %2, %3"     \
       : "=r" ((USItype) (sh)),                 \
         "=&r" ((USItype) (sl))                 \
       : "r" ((USItype) (ah)),                  \
         "rI" ((USItype) (bh)),                 \
         "r" ((USItype) (al)),                  \
         "rI" ((USItype) (bl)))
#define umul_ppmm(xh, xl, a, b) \
{register USItype __t0, __t1, __t2;                 \
  __asm__ ("%@ Inlined umul_ppmm\n"                 \
       "    mov %2, %5, lsr #16\n"              \
       "    mov %0, %6, lsr #16\n"              \
       "    bic %3, %5, %2, lsl #16\n"              \
       "    bic %4, %6, %0, lsl #16\n"              \
       "    mul %1, %3, %4\n"                   \
       "    mul %4, %2, %4\n"                   \
       "    mul %3, %0, %3\n"                   \
       "    mul %0, %2, %0\n"                   \
       "    adds    %3, %4, %3\n"                   \
       "    addcs   %0, %0, #65536\n"               \
       "    adds    %1, %1, %3, lsl #16\n"              \
       "    adc %0, %0, %3, lsr #16"                \
       : "=&r" ((USItype) (xh)),                    \
         "=r" ((USItype) (xl)),                 \
         "=&r" (__t0), "=&r" (__t1), "=r" (__t2)            \
       : "r" ((USItype) (a)),                   \
         "r" ((USItype) (b)));}
#define UMUL_TIME 20
#define UDIV_TIME 100
#endif /* __arm__ */

#if defined (__hppa) && W_TYPE_SIZE == 32
#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
  __asm__ ("add %4,%5,%1\n\taddc %2,%3,%0"              \
       : "=r" ((USItype) (sh)),                 \
         "=&r" ((USItype) (sl))                 \
       : "%rM" ((USItype) (ah)),                    \
         "rM" ((USItype) (bh)),                 \
         "%rM" ((USItype) (al)),                    \
         "rM" ((USItype) (bl)))
#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
  __asm__ ("sub %4,%5,%1\n\tsubb %2,%3,%0"              \
       : "=r" ((USItype) (sh)),                 \
         "=&r" ((USItype) (sl))                 \
       : "rM" ((USItype) (ah)),                 \
         "rM" ((USItype) (bh)),                 \
         "rM" ((USItype) (al)),                 \
         "rM" ((USItype) (bl)))
#if defined (_PA_RISC1_1)
#define umul_ppmm(w1, w0, u, v) \
  do {                                  \
    union                               \
      {                                 \
    UDItype __f;                            \
    struct {USItype __w1, __w0;} __w1w0;                \
      } __t;                                \
    __asm__ ("xmpyu %1,%2,%0"                       \
         : "=x" (__t.__f)                       \
         : "x" ((USItype) (u)),                 \
           "x" ((USItype) (v)));                    \
    (w1) = __t.__w1w0.__w1;                     \
    (w0) = __t.__w1w0.__w0;                     \
     } while (0)
#define UMUL_TIME 8
#else
#define UMUL_TIME 30
#endif
#define UDIV_TIME 40
#define count_leading_zeros(count, x) \
  do {                                  \
    USItype __tmp;                          \
    __asm__ (                               \
       "ldi     1,%0\n"                     \
"   extru,=     %1,15,16,%%r0       ; Bits 31..16 zero?\n"  \
"   extru,tr    %1,15,16,%1     ; No.  Shift down, skip add.\n"\
"   ldo     16(%0),%0       ; Yes.  Perform add.\n" \
"   extru,=     %1,23,8,%%r0        ; Bits 15..8 zero?\n"   \
"   extru,tr    %1,23,8,%1      ; No.  Shift down, skip add.\n"\
"   ldo     8(%0),%0        ; Yes.  Perform add.\n" \
"   extru,=     %1,27,4,%%r0        ; Bits 7..4 zero?\n"    \
"   extru,tr    %1,27,4,%1      ; No.  Shift down, skip add.\n"\
"   ldo     4(%0),%0        ; Yes.  Perform add.\n" \
"   extru,=     %1,29,2,%%r0        ; Bits 3..2 zero?\n"    \
"   extru,tr    %1,29,2,%1      ; No.  Shift down, skip add.\n"\
"   ldo     2(%0),%0        ; Yes.  Perform add.\n" \
"   extru       %1,30,1,%1      ; Extract bit 1.\n" \
"   sub     %0,%1,%0        ; Subtract it.\n"   \
    : "=r" (count), "=r" (__tmp) : "1" (x));            \
  } while (0)
#endif

#if (defined (__i370__) || defined (__s390__) || defined (__mvs__)) && W_TYPE_SIZE == 32
#define smul_ppmm(xh, xl, m0, m1) \
  do {                                  \
    union {DItype __ll;                         \
       struct {USItype __h, __l;} __i;              \
      } __x;                            \
    __asm__ ("lr %N0,%1\n\tmr %0,%2"                    \
         : "=&r" (__x.__ll)                     \
         : "r" (m0), "r" (m1));                 \
    (xh) = __x.__i.__h; (xl) = __x.__i.__l;             \
  } while (0)
#define sdiv_qrnnd(q, r, n1, n0, d) \
  do {                                  \
    union {DItype __ll;                         \
       struct {USItype __h, __l;} __i;              \
      } __x;                            \
    __x.__i.__h = n1; __x.__i.__l = n0;                 \
    __asm__ ("dr %0,%2"                         \
         : "=r" (__x.__ll)                      \
         : "0" (__x.__ll), "r" (d));                \
    (q) = __x.__i.__l; (r) = __x.__i.__h;               \
  } while (0)
#endif

#if (defined (__i386__) || defined (__i486__)) && W_TYPE_SIZE == 32
#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
  __asm__ ("addl %5,%1\n\tadcl %3,%0"                   \
       : "=r" ((USItype) (sh)),                 \
         "=&r" ((USItype) (sl))                 \
       : "%0" ((USItype) (ah)),                 \
         "g" ((USItype) (bh)),                  \
         "%1" ((USItype) (al)),                 \
         "g" ((USItype) (bl)))
#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
  __asm__ ("subl %5,%1\n\tsbbl %3,%0"                   \
       : "=r" ((USItype) (sh)),                 \
         "=&r" ((USItype) (sl))                 \
       : "0" ((USItype) (ah)),                  \
         "g" ((USItype) (bh)),                  \
         "1" ((USItype) (al)),                  \
         "g" ((USItype) (bl)))
#define umul_ppmm(w1, w0, u, v) \
  __asm__ ("mull %3"                            \
       : "=a" ((USItype) (w0)),                 \
         "=d" ((USItype) (w1))                  \
       : "%0" ((USItype) (u)),                  \
         "rm" ((USItype) (v)))
#define udiv_qrnnd(q, r, n1, n0, dv) \
  __asm__ ("divl %4"                            \
       : "=a" ((USItype) (q)),                  \
         "=d" ((USItype) (r))                   \
       : "0" ((USItype) (n0)),                  \
         "1" ((USItype) (n1)),                  \
         "rm" ((USItype) (dv)))
#define count_leading_zeros(count, x) \
  do {                                  \
    USItype __cbtmp;                            \
    __asm__ ("bsrl %1,%0"                       \
         : "=r" (__cbtmp) : "rm" ((USItype) (x)));          \
    (count) = __cbtmp ^ 31;                     \
  } while (0)
#define count_trailing_zeros(count, x) \
  __asm__ ("bsfl %1,%0" : "=r" (count) : "rm" ((USItype)(x)))
#define UMUL_TIME 40
#define UDIV_TIME 40
#endif /* 80x86 */

#if defined (__i960__) && W_TYPE_SIZE == 32
#define umul_ppmm(w1, w0, u, v) \
  ({union {UDItype __ll;                        \
       struct {USItype __l, __h;} __i;              \
      } __xx;                           \
  __asm__ ("emul    %2,%1,%0"                   \
       : "=d" (__xx.__ll)                       \
       : "%dI" ((USItype) (u)),                 \
         "dI" ((USItype) (v)));                 \
  (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;})
#define __umulsidi3(u, v) \
  ({UDItype __w;                            \
    __asm__ ("emul  %2,%1,%0"                   \
         : "=d" (__w)                       \
         : "%dI" ((USItype) (u)),                   \
           "dI" ((USItype) (v)));                   \
    __w; })
#endif /* __i960__ */

#if defined (__M32R__) && W_TYPE_SIZE == 32
#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
  /* The cmp clears the condition bit.  */ \
  __asm__ ("cmp %0,%0\n\taddx %%5,%1\n\taddx %%3,%0"            \
       : "=r" ((USItype) (sh)),                 \
         "=&r" ((USItype) (sl))                 \
       : "%0" ((USItype) (ah)),                 \
         "r" ((USItype) (bh)),                  \
         "%1" ((USItype) (al)),                 \
         "r" ((USItype) (bl))                   \
       : "cbit")
#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
  /* The cmp clears the condition bit.  */ \
  __asm__ ("cmp %0,%0\n\tsubx %5,%1\n\tsubx %3,%0"          \
       : "=r" ((USItype) (sh)),                 \
         "=&r" ((USItype) (sl))                 \
       : "0" ((USItype) (ah)),                  \
         "r" ((USItype) (bh)),                  \
         "1" ((USItype) (al)),                  \
         "r" ((USItype) (bl))                   \
       : "cbit")
#endif /* __M32R__ */

#if defined (__mc68000__) && W_TYPE_SIZE == 32
#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
  __asm__ ("add%.l %5,%1\n\taddx%.l %3,%0"              \
       : "=d" ((USItype) (sh)),                 \
         "=&d" ((USItype) (sl))                 \
       : "%0" ((USItype) (ah)),                 \
         "d" ((USItype) (bh)),                  \
         "%1" ((USItype) (al)),                 \
         "g" ((USItype) (bl)))
#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
  __asm__ ("sub%.l %5,%1\n\tsubx%.l %3,%0"              \
       : "=d" ((USItype) (sh)),                 \
         "=&d" ((USItype) (sl))                 \
       : "0" ((USItype) (ah)),                  \
         "d" ((USItype) (bh)),                  \
         "1" ((USItype) (al)),                  \
         "g" ((USItype) (bl)))

/* The '020, '030, '040 and CPU32 have 32x32->64 and 64/32->32q-32r.  */
#if defined (__mc68020__) || defined(mc68020) \
    || defined(__mc68030__) || defined(mc68030) \
    || defined(__mc68040__) || defined(mc68040) \
    || defined(__mcpu32__) || defined(mcpu32)
#define umul_ppmm(w1, w0, u, v) \
  __asm__ ("mulu%.l %3,%1:%0"                       \
       : "=d" ((USItype) (w0)),                 \
         "=d" ((USItype) (w1))                  \
       : "%0" ((USItype) (u)),                  \
         "dmi" ((USItype) (v)))
#define UMUL_TIME 45
#define udiv_qrnnd(q, r, n1, n0, d) \
  __asm__ ("divu%.l %4,%1:%0"                       \
       : "=d" ((USItype) (q)),                  \
         "=d" ((USItype) (r))                   \
       : "0" ((USItype) (n0)),                  \
         "1" ((USItype) (n1)),                  \
         "dmi" ((USItype) (d)))
#define UDIV_TIME 90
#define sdiv_qrnnd(q, r, n1, n0, d) \
  __asm__ ("divs%.l %4,%1:%0"                       \
       : "=d" ((USItype) (q)),                  \
         "=d" ((USItype) (r))                   \
       : "0" ((USItype) (n0)),                  \
         "1" ((USItype) (n1)),                  \
         "dmi" ((USItype) (d)))

#else /* not mc68020 */
#if !defined(__mcf5200__)
/* %/ inserts REGISTER_PREFIX, %# inserts IMMEDIATE_PREFIX.  */
#define umul_ppmm(xh, xl, a, b) \
  __asm__ ("| Inlined umul_ppmm\n"                  \
       "    move%.l %2,%/d0\n"                  \
       "    move%.l %3,%/d1\n"                  \
       "    move%.l %/d0,%/d2\n"                    \
       "    swap    %/d0\n"                     \
       "    move%.l %/d1,%/d3\n"                    \
       "    swap    %/d1\n"                     \
       "    move%.w %/d2,%/d4\n"                    \
       "    mulu    %/d3,%/d4\n"                    \
       "    mulu    %/d1,%/d2\n"                    \
       "    mulu    %/d0,%/d3\n"                    \
       "    mulu    %/d0,%/d1\n"                    \
       "    move%.l %/d4,%/d0\n"                    \
       "    eor%.w  %/d0,%/d0\n"                    \
       "    swap    %/d0\n"                     \
       "    add%.l  %/d0,%/d2\n"                    \
       "    add%.l  %/d3,%/d2\n"                    \
       "    jcc 1f\n"                       \
       "    add%.l  %#65536,%/d1\n"                 \
       "1:  swap    %/d2\n"                     \
       "    moveq   %#0,%/d0\n"                 \
       "    move%.w %/d2,%/d0\n"                    \
       "    move%.w %/d4,%/d2\n"                    \
       "    move%.l %/d2,%1\n"                  \
       "    add%.l  %/d1,%/d0\n"                    \
       "    move%.l %/d0,%0"                    \
       : "=g" ((USItype) (xh)),                 \
         "=g" ((USItype) (xl))                  \
       : "g" ((USItype) (a)),                   \
         "g" ((USItype) (b))                    \
       : "d0", "d1", "d2", "d3", "d4")
#define UMUL_TIME 100
#define UDIV_TIME 400
#endif /* not mcf5200 */
#endif /* not mc68020 */

/* The '020, '030, '040 and '060 have bitfield insns.  */
#if defined (__mc68020__) || defined(mc68020) \
    || defined(__mc68030__) || defined(mc68030) \
    || defined(__mc68040__) || defined(mc68040) \
    || defined(__mc68060__) || defined(mc68060)
#define count_leading_zeros(count, x) \
  __asm__ ("bfffo %1{%b2:%b2},%0"                   \
       : "=d" ((USItype) (count))                   \
       : "od" ((USItype) (x)), "n" (0))
#endif
#endif /* mc68000 */

#if defined (__m88000__) && W_TYPE_SIZE == 32
#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
  __asm__ ("addu.co %1,%r4,%r5\n\taddu.ci %0,%r2,%r3"           \
       : "=r" ((USItype) (sh)),                 \
         "=&r" ((USItype) (sl))                 \
       : "%rJ" ((USItype) (ah)),                    \
         "rJ" ((USItype) (bh)),                 \
         "%rJ" ((USItype) (al)),                    \
         "rJ" ((USItype) (bl)))
#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
  __asm__ ("subu.co %1,%r4,%r5\n\tsubu.ci %0,%r2,%r3"           \
       : "=r" ((USItype) (sh)),                 \
         "=&r" ((USItype) (sl))                 \
       : "rJ" ((USItype) (ah)),                 \
         "rJ" ((USItype) (bh)),                 \
         "rJ" ((USItype) (al)),                 \
         "rJ" ((USItype) (bl)))
#define count_leading_zeros(count, x) \
  do {                                  \
    USItype __cbtmp;                            \
    __asm__ ("ff1 %0,%1"                        \
         : "=r" (__cbtmp)                       \
         : "r" ((USItype) (x)));                    \
    (count) = __cbtmp ^ 31;                     \
  } while (0)
#define COUNT_LEADING_ZEROS_0 63 /* sic */
#if defined (__mc88110__)
#define umul_ppmm(wh, wl, u, v) \
  do {                                  \
    union {UDItype __ll;                        \
       struct {USItype __h, __l;} __i;              \
      } __xx;                           \
    __asm__ ("mulu.d    %0,%1,%2"                   \
         : "=r" (__xx.__ll)                     \
         : "r" ((USItype) (u)),                 \
           "r" ((USItype) (v)));                    \
    (wh) = __xx.__i.__h;                        \
    (wl) = __xx.__i.__l;                        \
  } while (0)
#define udiv_qrnnd(q, r, n1, n0, d) \
  ({union {UDItype __ll;                        \
       struct {USItype __h, __l;} __i;              \
      } __xx;                           \
  USItype __q;                              \
  __xx.__i.__h = (n1); __xx.__i.__l = (n0);             \
  __asm__ ("divu.d %0,%1,%2"                        \
       : "=r" (__q)                         \
       : "r" (__xx.__ll),                       \
         "r" ((USItype) (d)));                  \
  (r) = (n0) - __q * (d); (q) = __q; })
#define UMUL_TIME 5
#define UDIV_TIME 25
#else
#define UMUL_TIME 17
#define UDIV_TIME 150
#endif /* __mc88110__ */
#endif /* __m88000__ */

#if defined (__mips__) && W_TYPE_SIZE == 32
#define umul_ppmm(w1, w0, u, v) \
  __asm__ ("multu %2,%3"                        \
       : "=l" ((USItype) (w0)),                 \
         "=h" ((USItype) (w1))                  \
       : "d" ((USItype) (u)),                   \
         "d" ((USItype) (v)))
#define UMUL_TIME 10
#define UDIV_TIME 100
#endif /* __mips__ */

#if defined (__ns32000__) && W_TYPE_SIZE == 32
#define umul_ppmm(w1, w0, u, v) \
  ({union {UDItype __ll;                        \
       struct {USItype __l, __h;} __i;              \
      } __xx;                           \
  __asm__ ("meid %2,%0"                         \
       : "=g" (__xx.__ll)                       \
       : "%0" ((USItype) (u)),                  \
         "g" ((USItype) (v)));                  \
  (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;})
#define __umulsidi3(u, v) \
  ({UDItype __w;                            \
    __asm__ ("meid %2,%0"                       \
         : "=g" (__w)                       \
         : "%0" ((USItype) (u)),                    \
           "g" ((USItype) (v)));                    \
    __w; })
#define udiv_qrnnd(q, r, n1, n0, d) \
  ({union {UDItype __ll;                        \
       struct {USItype __l, __h;} __i;              \
      } __xx;                           \
  __xx.__i.__h = (n1); __xx.__i.__l = (n0);             \
  __asm__ ("deid %2,%0"                         \
       : "=g" (__xx.__ll)                       \
       : "0" (__xx.__ll),                       \
         "g" ((USItype) (d)));                  \
  (r) = __xx.__i.__l; (q) = __xx.__i.__h; })
#define count_trailing_zeros(count,x) \
  do {                                  \
    __asm__ ("ffsd     %2,%0"                       \
            : "=r" ((USItype) (count))                  \
            : "0" ((USItype) 0),                    \
              "r" ((USItype) (x)));                 \
  } while (0)
#endif /* __ns32000__ */

/* FIXME: We should test _IBMR2 here when we add assembly support for the
   system vendor compilers.
   FIXME: What's needed for gcc PowerPC VxWorks?  __vxworks__ is not good
   enough, since that hits ARM and m68k too.  */
#if (defined (_ARCH_PPC)    /* AIX */               \
     || defined (_ARCH_PWR) /* AIX */               \
     || defined (_ARCH_COM) /* AIX */               \
     || defined (__powerpc__)   /* gcc */               \
     || defined (__POWERPC__)   /* BEOS */              \
     || defined (__ppc__)   /* Darwin */                \
     || defined (PPC)       /* GNU/Linux, SysV */           \
     ) && W_TYPE_SIZE == 32
#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
  do {                                  \
    if (__builtin_constant_p (bh) && (bh) == 0)             \
      __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{aze|addze} %0,%2"       \
         : "=r" (sh), "=&r" (sl) : "r" (ah), "%r" (al), "rI" (bl));\
    else if (__builtin_constant_p (bh) && (bh) == ~(USItype) 0)     \
      __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{ame|addme} %0,%2"       \
         : "=r" (sh), "=&r" (sl) : "r" (ah), "%r" (al), "rI" (bl));\
    else                                \
      __asm__ ("{a%I5|add%I5c} %1,%4,%5\n\t{ae|adde} %0,%2,%3"      \
         : "=r" (sh), "=&r" (sl)                    \
         : "%r" (ah), "r" (bh), "%r" (al), "rI" (bl));      \
  } while (0)
#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
  do {                                  \
    if (__builtin_constant_p (ah) && (ah) == 0)             \
      __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfze|subfze} %0,%2"   \
           : "=r" (sh), "=&r" (sl) : "r" (bh), "rI" (al), "r" (bl));\
    else if (__builtin_constant_p (ah) && (ah) == ~(USItype) 0)     \
      __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfme|subfme} %0,%2"   \
           : "=r" (sh), "=&r" (sl) : "r" (bh), "rI" (al), "r" (bl));\
    else if (__builtin_constant_p (bh) && (bh) == 0)            \
      __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{ame|addme} %0,%2"     \
           : "=r" (sh), "=&r" (sl) : "r" (ah), "rI" (al), "r" (bl));\
    else if (__builtin_constant_p (bh) && (bh) == ~(USItype) 0)     \
      __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{aze|addze} %0,%2"     \
           : "=r" (sh), "=&r" (sl) : "r" (ah), "rI" (al), "r" (bl));\
    else                                \
      __asm__ ("{sf%I4|subf%I4c} %1,%5,%4\n\t{sfe|subfe} %0,%3,%2"  \
           : "=r" (sh), "=&r" (sl)                  \
           : "r" (ah), "r" (bh), "rI" (al), "r" (bl));      \
  } while (0)
#define count_leading_zeros(count, x) \
  __asm__ ("{cntlz|cntlzw} %0,%1" : "=r" (count) : "r" (x))
#define COUNT_LEADING_ZEROS_0 32
#if defined (_ARCH_PPC) || defined (__powerpc__) || defined (__POWERPC__) \
  || defined (__ppc__) || defined (PPC) || defined (__vxworks__)
#define umul_ppmm(ph, pl, m0, m1) \
  do {                                  \
    USItype __m0 = (m0), __m1 = (m1);                   \
    __asm__ ("mulhwu %0,%1,%2" : "=r" (ph) : "%r" (m0), "r" (m1));  \
    (pl) = __m0 * __m1;                         \
  } while (0)
#define UMUL_TIME 15
#define smul_ppmm(ph, pl, m0, m1) \
  do {                                  \
    SItype __m0 = (m0), __m1 = (m1);                    \
    __asm__ ("mulhw %0,%1,%2" : "=r" (ph) : "%r" (m0), "r" (m1));   \
    (pl) = __m0 * __m1;                         \
  } while (0)
#define SMUL_TIME 14
#define UDIV_TIME 120
#elif defined (_ARCH_PWR)
#define UMUL_TIME 8
#define smul_ppmm(xh, xl, m0, m1) \
  __asm__ ("mul %0,%2,%3" : "=r" (xh), "=q" (xl) : "r" (m0), "r" (m1))
#define SMUL_TIME 4
#define sdiv_qrnnd(q, r, nh, nl, d) \
  __asm__ ("div %0,%2,%4" : "=r" (q), "=q" (r) : "r" (nh), "1" (nl), "r" (d))
#define UDIV_TIME 100
#endif
#endif /* 32-bit POWER architecture variants.  */

/* We should test _IBMR2 here when we add assembly support for the system
   vendor compilers.  */
#if (defined (_ARCH_PPC64) || defined (__powerpc64__)) && W_TYPE_SIZE == 64
#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
  do {                                  \
    if (__builtin_constant_p (bh) && (bh) == 0)             \
      __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{aze|addze} %0,%2"       \
         : "=r" (sh), "=&r" (sl) : "r" (ah), "%r" (al), "rI" (bl));\
    else if (__builtin_constant_p (bh) && (bh) == ~(UDItype) 0)     \
      __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{ame|addme} %0,%2"       \
         : "=r" (sh), "=&r" (sl) : "r" (ah), "%r" (al), "rI" (bl));\
    else                                \
      __asm__ ("{a%I5|add%I5c} %1,%4,%5\n\t{ae|adde} %0,%2,%3"      \
         : "=r" (sh), "=&r" (sl)                    \
         : "%r" (ah), "r" (bh), "%r" (al), "rI" (bl));      \
  } while (0)
#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
  do {                                  \
    if (__builtin_constant_p (ah) && (ah) == 0)             \
      __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfze|subfze} %0,%2"   \
           : "=r" (sh), "=&r" (sl) : "r" (bh), "rI" (al), "r" (bl));\
    else if (__builtin_constant_p (ah) && (ah) == ~(UDItype) 0)     \
      __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfme|subfme} %0,%2"   \
           : "=r" (sh), "=&r" (sl) : "r" (bh), "rI" (al), "r" (bl));\
    else if (__builtin_constant_p (bh) && (bh) == 0)            \
      __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{ame|addme} %0,%2"     \
           : "=r" (sh), "=&r" (sl) : "r" (ah), "rI" (al), "r" (bl));\
    else if (__builtin_constant_p (bh) && (bh) == ~(UDItype) 0)     \
      __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{aze|addze} %0,%2"     \
           : "=r" (sh), "=&r" (sl) : "r" (ah), "rI" (al), "r" (bl));\
    else                                \
      __asm__ ("{sf%I4|subf%I4c} %1,%5,%4\n\t{sfe|subfe} %0,%3,%2"  \
           : "=r" (sh), "=&r" (sl)                  \
           : "r" (ah), "r" (bh), "rI" (al), "r" (bl));      \
  } while (0)
#define count_leading_zeros(count, x) \
  __asm__ ("cntlzd %0,%1" : "=r" (count) : "r" (x))
#define COUNT_LEADING_ZEROS_0 64
#define umul_ppmm(ph, pl, m0, m1) \
  do {                                  \
    UDItype __m0 = (m0), __m1 = (m1);                   \
    __asm__ ("mulhdu %0,%1,%2" : "=r" (ph) : "%r" (m0), "r" (m1));  \
    (pl) = __m0 * __m1;                         \
  } while (0)
#define UMUL_TIME 15
#define smul_ppmm(ph, pl, m0, m1) \
  do {                                  \
    DItype __m0 = (m0), __m1 = (m1);                    \
    __asm__ ("mulhd %0,%1,%2" : "=r" (ph) : "%r" (m0), "r" (m1));   \
    (pl) = __m0 * __m1;                         \
  } while (0)
#define SMUL_TIME 14  /* ??? */
#define UDIV_TIME 120 /* ??? */
#endif /* 64-bit PowerPC.  */

#if defined (__ibm032__) /* RT/ROMP */ && W_TYPE_SIZE == 32
#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
  __asm__ ("a %1,%5\n\tae %0,%3"                    \
       : "=r" ((USItype) (sh)),                 \
         "=&r" ((USItype) (sl))                 \
       : "%0" ((USItype) (ah)),                 \
         "r" ((USItype) (bh)),                  \
         "%1" ((USItype) (al)),                 \
         "r" ((USItype) (bl)))
#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
  __asm__ ("s %1,%5\n\tse %0,%3"                    \
       : "=r" ((USItype) (sh)),                 \
         "=&r" ((USItype) (sl))                 \
       : "0" ((USItype) (ah)),                  \
         "r" ((USItype) (bh)),                  \
         "1" ((USItype) (al)),                  \
         "r" ((USItype) (bl)))
#define umul_ppmm(ph, pl, m0, m1) \
  do {                                  \
    USItype __m0 = (m0), __m1 = (m1);                   \
    __asm__ (                               \
       "s   r2,r2\n"                        \
"   mts r10,%2\n"                       \
"   m   r2,%3\n"                        \
"   m   r2,%3\n"                        \
"   m   r2,%3\n"                        \
"   m   r2,%3\n"                        \
"   m   r2,%3\n"                        \
"   m   r2,%3\n"                        \
"   m   r2,%3\n"                        \
"   m   r2,%3\n"                        \
"   m   r2,%3\n"                        \
"   m   r2,%3\n"                        \
"   m   r2,%3\n"                        \
"   m   r2,%3\n"                        \
"   m   r2,%3\n"                        \
"   m   r2,%3\n"                        \
"   m   r2,%3\n"                        \
"   m   r2,%3\n"                        \
"   cas %0,r2,r0\n"                     \
"   mfs r10,%1"                         \
         : "=r" ((USItype) (ph)),                   \
           "=r" ((USItype) (pl))                    \
         : "%r" (__m0),                     \
        "r" (__m1)                      \
         : "r2");                           \
    (ph) += ((((SItype) __m0 >> 31) & __m1)             \
         + (((SItype) __m1 >> 31) & __m0));             \
  } while (0)
#define UMUL_TIME 20
#define UDIV_TIME 200
#define count_leading_zeros(count, x) \
  do {                                  \
    if ((x) >= 0x10000)                         \
      __asm__ ("clz %0,%1"                      \
           : "=r" ((USItype) (count))               \
           : "r" ((USItype) (x) >> 16));                \
    else                                \
      {                                 \
    __asm__ ("clz   %0,%1"                      \
         : "=r" ((USItype) (count))             \
         : "r" ((USItype) (x)));                    \
    (count) += 16;                          \
      }                                 \
  } while (0)
#endif

#if defined (__sh2__) && W_TYPE_SIZE == 32
#define umul_ppmm(w1, w0, u, v) \
  __asm__ (                             \
       "dmulu.l %2,%3\n\tsts    macl,%1\n\tsts  mach,%0"        \
       : "=r" ((USItype)(w1)),                  \
         "=r" ((USItype)(w0))                   \
       : "r" ((USItype)(u)),                    \
         "r" ((USItype)(v))                     \
       : "macl", "mach")
#define UMUL_TIME 5
#endif

#if defined (__SH5__) && __SHMEDIA__ && W_TYPE_SIZE == 32
#define __umulsidi3(u,v) ((UDItype)(USItype)u*(USItype)v)
#define count_leading_zeros(count, x) \
  do                                    \
    {                                   \
      UDItype x_ = (USItype)(x);                    \
      SItype c_;                            \
                                    \
      __asm__ ("nsb %1, %0" : "=r" (c_) : "r" (x_));            \
      (count) = c_ - 31;                        \
    }                                   \
  while (0)
#define COUNT_LEADING_ZEROS_0 32
#endif

#if defined (__sparc__) && !defined (__arch64__) && !defined (__sparcv9) \
    && W_TYPE_SIZE == 32
#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
  __asm__ ("addcc %r4,%5,%1\n\taddx %r2,%3,%0"              \
       : "=r" ((USItype) (sh)),                 \
         "=&r" ((USItype) (sl))                 \
       : "%rJ" ((USItype) (ah)),                    \
         "rI" ((USItype) (bh)),                 \
         "%rJ" ((USItype) (al)),                    \
         "rI" ((USItype) (bl))                  \
       __CLOBBER_CC)
#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
  __asm__ ("subcc %r4,%5,%1\n\tsubx %r2,%3,%0"              \
       : "=r" ((USItype) (sh)),                 \
         "=&r" ((USItype) (sl))                 \
       : "rJ" ((USItype) (ah)),                 \
         "rI" ((USItype) (bh)),                 \
         "rJ" ((USItype) (al)),                 \
         "rI" ((USItype) (bl))                  \
       __CLOBBER_CC)
#if defined (__sparc_v8__)
#define umul_ppmm(w1, w0, u, v) \
  __asm__ ("umul %2,%3,%1;rd %%y,%0"                    \
       : "=r" ((USItype) (w1)),                 \
         "=r" ((USItype) (w0))                  \
       : "r" ((USItype) (u)),                   \
         "r" ((USItype) (v)))
#define udiv_qrnnd(__q, __r, __n1, __n0, __d) \
  __asm__ ("mov %2,%%y;nop;nop;nop;udiv %3,%4,%0;umul %0,%4,%1;sub %3,%1,%1"\
       : "=&r" ((USItype) (__q)),                   \
         "=&r" ((USItype) (__r))                    \
       : "r" ((USItype) (__n1)),                    \
         "r" ((USItype) (__n0)),                    \
         "r" ((USItype) (__d)))
#else
#if defined (__sparclite__)
/* This has hardware multiply but not divide.  It also has two additional
   instructions scan (ffs from high bit) and divscc.  */
#define umul_ppmm(w1, w0, u, v) \
  __asm__ ("umul %2,%3,%1;rd %%y,%0"                    \
       : "=r" ((USItype) (w1)),                 \
         "=r" ((USItype) (w0))                  \
       : "r" ((USItype) (u)),                   \
         "r" ((USItype) (v)))
#define udiv_qrnnd(q, r, n1, n0, d) \
  __asm__ ("! Inlined udiv_qrnnd\n"                 \
"   wr  %%g0,%2,%%y ! Not a delayed write for sparclite\n"  \
"   tst %%g0\n"                         \
"   divscc  %3,%4,%%g1\n"                       \
"   divscc  %%g1,%4,%%g1\n"                     \
"   divscc  %%g1,%4,%%g1\n"                     \
"   divscc  %%g1,%4,%%g1\n"                     \
"   divscc  %%g1,%4,%%g1\n"                     \
"   divscc  %%g1,%4,%%g1\n"                     \
"   divscc  %%g1,%4,%%g1\n"                     \
"   divscc  %%g1,%4,%%g1\n"                     \
"   divscc  %%g1,%4,%%g1\n"                     \
"   divscc  %%g1,%4,%%g1\n"                     \
"   divscc  %%g1,%4,%%g1\n"                     \
"   divscc  %%g1,%4,%%g1\n"                     \
"   divscc  %%g1,%4,%%g1\n"                     \
"   divscc  %%g1,%4,%%g1\n"                     \
"   divscc  %%g1,%4,%%g1\n"                     \
"   divscc  %%g1,%4,%%g1\n"                     \
"   divscc  %%g1,%4,%%g1\n"                     \
"   divscc  %%g1,%4,%%g1\n"                     \
"   divscc  %%g1,%4,%%g1\n"                     \
"   divscc  %%g1,%4,%%g1\n"                     \
"   divscc  %%g1,%4,%%g1\n"                     \
"   divscc  %%g1,%4,%%g1\n"                     \
"   divscc  %%g1,%4,%%g1\n"                     \
"   divscc  %%g1,%4,%%g1\n"                     \
"   divscc  %%g1,%4,%%g1\n"                     \
"   divscc  %%g1,%4,%%g1\n"                     \
"   divscc  %%g1,%4,%%g1\n"                     \
"   divscc  %%g1,%4,%%g1\n"                     \
"   divscc  %%g1,%4,%%g1\n"                     \
"   divscc  %%g1,%4,%%g1\n"                     \
"   divscc  %%g1,%4,%%g1\n"                     \
"   divscc  %%g1,%4,%0\n"                       \
"   rd  %%y,%1\n"                       \
"   bl,a 1f\n"                          \
"   add %1,%4,%1\n"                     \
"1: ! End of inline udiv_qrnnd"                 \
       : "=r" ((USItype) (q)),                  \
         "=r" ((USItype) (r))                   \
       : "r" ((USItype) (n1)),                  \
         "r" ((USItype) (n0)),                  \
         "rI" ((USItype) (d))                   \
       : "g1" __AND_CLOBBER_CC)
#define UDIV_TIME 37
#define count_leading_zeros(count, x) \
  do {                                                                  \
  __asm__ ("scan %1,1,%0"                                               \
           : "=r" ((USItype) (count))                                   \
           : "r" ((USItype) (x)));                  \
  } while (0)
/* Early sparclites return 63 for an argument of 0, but they warn that future
   implementations might change this.  Therefore, leave COUNT_LEADING_ZEROS_0
   undefined.  */
#else
/* SPARC without integer multiplication and divide instructions.
   (i.e. at least Sun4/20,40,60,65,75,110,260,280,330,360,380,470,490) */
#define umul_ppmm(w1, w0, u, v) \
  __asm__ ("! Inlined umul_ppmm\n"                  \
"   wr  %%g0,%2,%%y ! SPARC has 0-3 delay insn after a wr\n"\
"   sra %3,31,%%o5  ! Don't move this insn\n"       \
"   and %2,%%o5,%%o5    ! Don't move this insn\n"       \
"   andcc   %%g0,0,%%g1 ! Don't move this insn\n"       \
"   mulscc  %%g1,%3,%%g1\n"                     \
"   mulscc  %%g1,%3,%%g1\n"                     \
"   mulscc  %%g1,%3,%%g1\n"                     \
"   mulscc  %%g1,%3,%%g1\n"                     \
"   mulscc  %%g1,%3,%%g1\n"                     \
"   mulscc  %%g1,%3,%%g1\n"                     \
"   mulscc  %%g1,%3,%%g1\n"                     \
"   mulscc  %%g1,%3,%%g1\n"                     \
"   mulscc  %%g1,%3,%%g1\n"                     \
"   mulscc  %%g1,%3,%%g1\n"                     \
"   mulscc  %%g1,%3,%%g1\n"                     \
"   mulscc  %%g1,%3,%%g1\n"                     \
"   mulscc  %%g1,%3,%%g1\n"                     \
"   mulscc  %%g1,%3,%%g1\n"                     \
"   mulscc  %%g1,%3,%%g1\n"                     \
"   mulscc  %%g1,%3,%%g1\n"                     \
"   mulscc  %%g1,%3,%%g1\n"                     \
"   mulscc  %%g1,%3,%%g1\n"                     \
"   mulscc  %%g1,%3,%%g1\n"                     \
"   mulscc  %%g1,%3,%%g1\n"                     \
"   mulscc  %%g1,%3,%%g1\n"                     \
"   mulscc  %%g1,%3,%%g1\n"                     \
"   mulscc  %%g1,%3,%%g1\n"                     \
"   mulscc  %%g1,%3,%%g1\n"                     \
"   mulscc  %%g1,%3,%%g1\n"                     \
"   mulscc  %%g1,%3,%%g1\n"                     \
"   mulscc  %%g1,%3,%%g1\n"                     \
"   mulscc  %%g1,%3,%%g1\n"                     \
"   mulscc  %%g1,%3,%%g1\n"                     \
"   mulscc  %%g1,%3,%%g1\n"                     \
"   mulscc  %%g1,%3,%%g1\n"                     \
"   mulscc  %%g1,%3,%%g1\n"                     \
"   mulscc  %%g1,0,%%g1\n"                      \
"   add %%g1,%%o5,%0\n"                     \
"   rd  %%y,%1"                         \
       : "=r" ((USItype) (w1)),                 \
         "=r" ((USItype) (w0))                  \
       : "%rI" ((USItype) (u)),                 \
         "r" ((USItype) (v))                        \
       : "g1", "o5" __AND_CLOBBER_CC)
#define UMUL_TIME 39        /* 39 instructions */
/* It's quite necessary to add this much assembler for the sparc.
   The default udiv_qrnnd (in C) is more than 10 times slower!  */
#define udiv_qrnnd(__q, __r, __n1, __n0, __d) \
  __asm__ ("! Inlined udiv_qrnnd\n"                 \
"   mov 32,%%g1\n"                      \
"   subcc   %1,%2,%%g0\n"                       \
"1: bcs 5f\n"                           \
"    addxcc %0,%0,%0    ! shift n1n0 and a q-bit in lsb\n"  \
"   sub %1,%2,%1    ! this kills msb of n\n"        \
"   addx    %1,%1,%1    ! so this can't give carry\n"       \
"   subcc   %%g1,1,%%g1\n"                      \
"2: bne 1b\n"                           \
"    subcc  %1,%2,%%g0\n"                       \
"   bcs 3f\n"                           \
"    addxcc %0,%0,%0    ! shift n1n0 and a q-bit in lsb\n"  \
"   b   3f\n"                           \
"    sub    %1,%2,%1    ! this kills msb of n\n"        \
"4: sub %1,%2,%1\n"                     \
"5: addxcc  %1,%1,%1\n"                     \
"   bcc 2b\n"                           \
"    subcc  %%g1,1,%%g1\n"                      \
"! Got carry from n.  Subtract next step to cancel this carry.\n"   \
"   bne 4b\n"                           \
"    addcc  %0,%0,%0    ! shift n1n0 and a 0-bit in lsb\n"  \
"   sub %1,%2,%1\n"                     \
"3: xnor    %0,0,%0\n"                      \
"   ! End of inline udiv_qrnnd"                 \
       : "=&r" ((USItype) (__q)),                   \
         "=&r" ((USItype) (__r))                    \
       : "r" ((USItype) (__d)),                 \
         "1" ((USItype) (__n1)),                    \
         "0" ((USItype) (__n0)) : "g1" __AND_CLOBBER_CC)
#define UDIV_TIME (3+7*32)  /* 7 instructions/iteration. 32 iterations.  */
#endif /* __sparclite__ */
#endif /* __sparc_v8__ */
#endif /* sparc32 */

#if ((defined (__sparc__) && defined (__arch64__)) || defined (__sparcv9)) \
    && W_TYPE_SIZE == 64
#define add_ssaaaa(sh, sl, ah, al, bh, bl)              \
  __asm__ ("addcc %r4,%5,%1\n\t"                    \
       "add %r2,%3,%0\n\t"                      \
       "bcs,a,pn %%xcc, 1f\n\t"                 \
       "add %0, 1, %0\n"                        \
       "1:"                             \
       : "=r" ((UDItype)(sh)),                      \
         "=&r" ((UDItype)(sl))                      \
       : "%rJ" ((UDItype)(ah)),                     \
         "rI" ((UDItype)(bh)),                      \
         "%rJ" ((UDItype)(al)),                     \
         "rI" ((UDItype)(bl))                       \
       __CLOBBER_CC)

#define sub_ddmmss(sh, sl, ah, al, bh, bl)              \
  __asm__ ("subcc %r4,%5,%1\n\t"                    \
       "sub %r2,%3,%0\n\t"                      \
       "bcs,a,pn %%xcc, 1f\n\t"                 \
       "sub %0, 1, %0\n\t"                      \
       "1:"                             \
       : "=r" ((UDItype)(sh)),                      \
         "=&r" ((UDItype)(sl))                      \
       : "rJ" ((UDItype)(ah)),                      \
         "rI" ((UDItype)(bh)),                      \
         "rJ" ((UDItype)(al)),                      \
         "rI" ((UDItype)(bl))                       \
       __CLOBBER_CC)

#define umul_ppmm(wh, wl, u, v)                     \
  do {                                  \
      UDItype tmp1, tmp2, tmp3, tmp4;               \
      __asm__ __volatile__ (                    \
           "srl %7,0,%3\n\t"                    \
           "mulx %3,%6,%1\n\t"                  \
           "srlx %6,32,%2\n\t"                  \
           "mulx %2,%3,%4\n\t"                  \
           "sllx %4,32,%5\n\t"                  \
           "srl %6,0,%3\n\t"                    \
           "sub %1,%5,%5\n\t"                   \
           "srlx %5,32,%5\n\t"                  \
           "addcc %4,%5,%4\n\t"                 \
           "srlx %7,32,%5\n\t"                  \
           "mulx %3,%5,%3\n\t"                  \
           "mulx %2,%5,%5\n\t"                  \
           "sethi %%hi(0x80000000),%2\n\t"          \
           "addcc %4,%3,%4\n\t"                 \
           "srlx %4,32,%4\n\t"                  \
           "add %2,%2,%2\n\t"                   \
           "movcc %%xcc,%%g0,%2\n\t"                \
           "addcc %5,%4,%5\n\t"                 \
           "sllx %3,32,%3\n\t"                  \
           "add %1,%3,%1\n\t"                   \
           "add %5,%2,%0"                   \
       : "=r" ((UDItype)(wh)),                  \
         "=&r" ((UDItype)(wl)),                 \
         "=&r" (tmp1), "=&r" (tmp2), "=&r" (tmp3), "=&r" (tmp4) \
       : "r" ((UDItype)(u)),                    \
         "r" ((UDItype)(v))                     \
       __CLOBBER_CC);                       \
  } while (0)
#define UMUL_TIME 96
#define UDIV_TIME 230
#endif /* sparc64 */

#if defined (__vax__) && W_TYPE_SIZE == 32
#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
  __asm__ ("addl2 %5,%1\n\tadwc %3,%0"                  \
       : "=g" ((USItype) (sh)),                 \
         "=&g" ((USItype) (sl))                 \
       : "%0" ((USItype) (ah)),                 \
         "g" ((USItype) (bh)),                  \
         "%1" ((USItype) (al)),                 \
         "g" ((USItype) (bl)))
#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
  __asm__ ("subl2 %5,%1\n\tsbwc %3,%0"                  \
       : "=g" ((USItype) (sh)),                 \
         "=&g" ((USItype) (sl))                 \
       : "0" ((USItype) (ah)),                  \
         "g" ((USItype) (bh)),                  \
         "1" ((USItype) (al)),                  \
         "g" ((USItype) (bl)))
#define umul_ppmm(xh, xl, m0, m1) \
  do {                                  \
    union {                             \
    UDItype __ll;                           \
    struct {USItype __l, __h;} __i;                 \
      } __xx;                               \
    USItype __m0 = (m0), __m1 = (m1);                   \
    __asm__ ("emul %1,%2,$0,%0"                     \
         : "=r" (__xx.__ll)                     \
         : "g" (__m0),                      \
           "g" (__m1));                     \
    (xh) = __xx.__i.__h;                        \
    (xl) = __xx.__i.__l;                        \
    (xh) += ((((SItype) __m0 >> 31) & __m1)             \
         + (((SItype) __m1 >> 31) & __m0));             \
  } while (0)
#define sdiv_qrnnd(q, r, n1, n0, d) \
  do {                                  \
    union {DItype __ll;                         \
       struct {SItype __l, __h;} __i;               \
      } __xx;                           \
    __xx.__i.__h = n1; __xx.__i.__l = n0;               \
    __asm__ ("ediv %3,%2,%0,%1"                     \
         : "=g" (q), "=g" (r)                   \
         : "g" (__xx.__ll), "g" (d));               \
  } while (0)
#endif /* __vax__ */

#if defined (__z8000__) && W_TYPE_SIZE == 16
#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
  __asm__ ("add %H1,%H5\n\tadc  %H0,%H3"                \
       : "=r" ((unsigned int)(sh)),                 \
         "=&r" ((unsigned int)(sl))                 \
       : "%0" ((unsigned int)(ah)),                 \
         "r" ((unsigned int)(bh)),                  \
         "%1" ((unsigned int)(al)),                 \
         "rQR" ((unsigned int)(bl)))
#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
  __asm__ ("sub %H1,%H5\n\tsbc  %H0,%H3"                \
       : "=r" ((unsigned int)(sh)),                 \
         "=&r" ((unsigned int)(sl))                 \
       : "0" ((unsigned int)(ah)),                  \
         "r" ((unsigned int)(bh)),                  \
         "1" ((unsigned int)(al)),                  \
         "rQR" ((unsigned int)(bl)))
#define umul_ppmm(xh, xl, m0, m1) \
  do {                                  \
    union {long int __ll;                       \
       struct {unsigned int __h, __l;} __i;             \
      } __xx;                           \
    unsigned int __m0 = (m0), __m1 = (m1);              \
    __asm__ ("mult  %S0,%H3"                    \
         : "=r" (__xx.__i.__h),                 \
           "=r" (__xx.__i.__l)                  \
         : "%1" (__m0),                     \
           "rQR" (__m1));                       \
    (xh) = __xx.__i.__h; (xl) = __xx.__i.__l;               \
    (xh) += ((((signed int) __m0 >> 15) & __m1)             \
         + (((signed int) __m1 >> 15) & __m0));         \
  } while (0)
#endif /* __z8000__ */

#endif /* __GNUC__ */

/* If this machine has no inline assembler, use C macros.  */

#if !defined (add_ssaaaa)
#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
  do {                                  \
    UWtype __x;                             \
    __x = (al) + (bl);                          \
    (sh) = (ah) + (bh) + (__x < (al));                  \
    (sl) = __x;                             \
  } while (0)
#endif

#if !defined (sub_ddmmss)
#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
  do {                                  \
    UWtype __x;                             \
    __x = (al) - (bl);                          \
    (sh) = (ah) - (bh) - (__x > (al));                  \
    (sl) = __x;                             \
  } while (0)
#endif

/* If we lack umul_ppmm but have smul_ppmm, define umul_ppmm in terms of
   smul_ppmm.  */
#if !defined (umul_ppmm) && defined (smul_ppmm)
#define umul_ppmm(w1, w0, u, v)                     \
  do {                                  \
    UWtype __w1;                            \
    UWtype __xm0 = (u), __xm1 = (v);                    \
    smul_ppmm (__w1, w0, __xm0, __xm1);                 \
    (w1) = __w1 + (-(__xm0 >> (W_TYPE_SIZE - 1)) & __xm1)       \
        + (-(__xm1 >> (W_TYPE_SIZE - 1)) & __xm0);      \
  } while (0)
#endif

/* If we still don't have umul_ppmm, define it using plain C.  */
#if !defined (umul_ppmm)
#define umul_ppmm(w1, w0, u, v)                     \
  do {                                  \
    UWtype __x0, __x1, __x2, __x3;                  \
    UHWtype __ul, __vl, __uh, __vh;                 \
                                    \
    __ul = __ll_lowpart (u);                        \
    __uh = __ll_highpart (u);                       \
    __vl = __ll_lowpart (v);                        \
    __vh = __ll_highpart (v);                       \
                                    \
    __x0 = (UWtype) __ul * __vl;                    \
    __x1 = (UWtype) __ul * __vh;                    \
    __x2 = (UWtype) __uh * __vl;                    \
    __x3 = (UWtype) __uh * __vh;                    \
                                    \
    __x1 += __ll_highpart (__x0);/* this can't give carry */        \
    __x1 += __x2;       /* but this indeed can */       \
    if (__x1 < __x2)        /* did we get it? */            \
      __x3 += __ll_B;       /* yes, add it in the proper pos.  */   \
                                    \
    (w1) = __x3 + __ll_highpart (__x1);                 \
    (w0) = __ll_lowpart (__x1) * __ll_B + __ll_lowpart (__x0);      \
  } while (0)
#endif

#if !defined (__umulsidi3)
#define __umulsidi3(u, v) \
  ({DWunion __w;                            \
    umul_ppmm (__w.s.high, __w.s.low, u, v);                \
    __w.ll; })
#endif

/* Define this unconditionally, so it can be used for debugging.  */
#define __udiv_qrnnd_c(q, r, n1, n0, d) \
  do {                                  \
    UWtype __d1, __d0, __q1, __q0;                  \
    UWtype __r1, __r0, __m;                     \
    __d1 = __ll_highpart (d);                       \
    __d0 = __ll_lowpart (d);                        \
                                    \
    __r1 = (n1) % __d1;                         \
    __q1 = (n1) / __d1;                         \
    __m = (UWtype) __q1 * __d0;                     \
    __r1 = __r1 * __ll_B | __ll_highpart (n0);              \
    if (__r1 < __m)                         \
      {                                 \
    __q1--, __r1 += (d);                        \
    if (__r1 >= (d)) /* i.e. we didn't get carry when adding to __r1 */\
      if (__r1 < __m)                       \
        __q1--, __r1 += (d);                    \
      }                                 \
    __r1 -= __m;                            \
                                    \
    __r0 = __r1 % __d1;                         \
    __q0 = __r1 / __d1;                         \
    __m = (UWtype) __q0 * __d0;                     \
    __r0 = __r0 * __ll_B | __ll_lowpart (n0);               \
    if (__r0 < __m)                         \
      {                                 \
    __q0--, __r0 += (d);                        \
    if (__r0 >= (d))                        \
      if (__r0 < __m)                       \
        __q0--, __r0 += (d);                    \
      }                                 \
    __r0 -= __m;                            \
                                    \
    (q) = (UWtype) __q1 * __ll_B | __q0;                \
    (r) = __r0;                             \
  } while (0)

/* If the processor has no udiv_qrnnd but sdiv_qrnnd, go through
   __udiv_w_sdiv (defined in libgcc or elsewhere).  */
#if !defined (udiv_qrnnd) && defined (sdiv_qrnnd)
#define udiv_qrnnd(q, r, nh, nl, d) \
  do {                                  \
    USItype __r;                            \
    (q) = __udiv_w_sdiv (&__r, nh, nl, d);              \
    (r) = __r;                              \
  } while (0)
#endif

/* If udiv_qrnnd was not defined for this processor, use __udiv_qrnnd_c.  */
#if !defined (udiv_qrnnd)
#define UDIV_NEEDS_NORMALIZATION 1
#define udiv_qrnnd __udiv_qrnnd_c
#endif

#if !defined (count_leading_zeros)
extern const UQItype __clz_tab[];
#define count_leading_zeros(count, x) \
  do {                                  \
    UWtype __xr = (x);                          \
    UWtype __a;                             \
                                    \
    if (W_TYPE_SIZE <= 32)                      \
      {                                 \
    __a = __xr < ((UWtype)1<<2*__BITS4)             \
      ? (__xr < ((UWtype)1<<__BITS4) ? 0 : __BITS4)         \
      : (__xr < ((UWtype)1<<3*__BITS4) ?  2*__BITS4 : 3*__BITS4);   \
      }                                 \
    else                                \
      {                                 \
    for (__a = W_TYPE_SIZE - 8; __a > 0; __a -= 8)          \
      if (((__xr >> __a) & 0xff) != 0)              \
        break;                          \
      }                                 \
                                    \
    (count) = W_TYPE_SIZE - (__clz_tab[__xr >> __a] + __a);     \
  } while (0)
#define COUNT_LEADING_ZEROS_0 W_TYPE_SIZE
#endif

#if !defined (count_trailing_zeros)
/* Define count_trailing_zeros using count_leading_zeros.  The latter might be
   defined in asm, but if it is not, the C version above is good enough.  */
#define count_trailing_zeros(count, x) \
  do {                                  \
    UWtype __ctz_x = (x);                       \
    UWtype __ctz_c;                         \
    count_leading_zeros (__ctz_c, __ctz_x & -__ctz_x);          \
    (count) = W_TYPE_SIZE - 1 - __ctz_c;                \
  } while (0)
#endif



static unsigned long divmodsi4(int modwanted, unsigned long num, unsigned long den){
  long int bit = 1;				
  long int res = 0;				
  long prevden;
  while (den < num && bit && !(den & (1L<<31)))			       
    {
      den <<=1;					
      bit <<=1;					
    }						
  while (bit)
    {					
      if (num >= den)
	{				
	  num -= den;				
	  res |= bit;				
	}						
      bit >>=1;					
      den >>=1;					
    }						
  if (modwanted) return num;
  return res;
}


#define exitdiv(sign, res) if (sign) { res = - res;} return res;

long __modsi3 (long numerator, long denominator){
  int sign = 0;
  long dividend;
  long modul;


  if (numerator < 0) 
    {
      numerator = -numerator;
      sign = 1;
    }
  if (denominator < 0)
    {
      denominator = -denominator;
    }  
  
  modul =  divmodsi4 (1, numerator, denominator);
  if (sign)
    return - modul;
  return modul;
}


long __divsi3 (long numerator, long denominator){
  int sign;
  long dividend;
  long modul;
  divnorm (numerator, denominator, sign);

  dividend = divmodsi4 (0,  numerator, denominator);
  exitdiv (sign, dividend);
}

long __umodsi3 (unsigned long numerator, unsigned long denominator){
  long dividend;
  long modul;

  modul= divmodsi4 (1,  numerator, denominator);
  return modul;
}

long __udivsi3 (unsigned long numerator, unsigned long denominator){
  int sign;
  long dividend;
  long modul;
  dividend =   divmodsi4 (0, numerator, denominator);
  return dividend;
}




long long __moddi3(long long a, long long b){
    int sa;
    int sb;
    unsigned long long tempah = 0;
    unsigned long long tempal;
    if(a>=0){
      sa = 0;
      tempal = a;
    }else{
      sa = 1;
      tempal = -a;
    }
    
    unsigned long long tempbh = b;
    unsigned long long tempbl = 0;
    if(b>=0){
      sb = 0;
      tempbh = b;
    }else{
      sb = 1;
      tempbh = -b;
    }
    
    unsigned long long q = 0;
    int i;
    for (i = 0; i <= 64; i++)
    {
        q <<= 1;
        if ((tempah > tempbh) || (tempah == tempbh && tempal >= tempbl))
        {
            //tempa -= tempb;
            if (tempal < tempbl)
            {
                tempah--;
            }
            tempal -= tempbl;
            tempah -= tempbh;
            q++;
        }
        //tempb >>= 1;
        tempbl >>= 1;
        if ((tempbh & 1) == 1) {
            tempbl |= 0x8000000000000000LL;
        }
        tempbh >>= 1;
    }
    long long ret;
    if((sa ^ sb)==0){
      ret = tempal;
    }else{
      ret = -tempal;
    }
    return ret;
}


long long __divdi3(long long a, long long b){
    int sa;
    int sb;
    unsigned long long tempah = 0;
    unsigned long long tempal;
    if(a>=0){
      sa = 0;
      tempal = a;
    }else{
      sa = 1;
      tempal = -a;
    }
    
    unsigned long long tempbh = b;
    unsigned long long tempbl = 0;
    if(b>=0){
      sb = 0;
      tempbh = b;
    }else{
      sb = 1;
      tempbh = -b;
    }
    
    unsigned long long q = 0;
    int i;
    for (i = 0; i <= 64; i++)
    {
        q <<= 1;
        if ((tempah > tempbh) || (tempah == tempbh && tempal >= tempbl))
        {
            //tempa -= tempb;
            if (tempal < tempbl)
            {
                tempah--;
            }
            tempal -= tempbl;
            tempah -= tempbh;
            q++;
        }
        //tempb >>= 1;
        tempbl >>= 1;
        if ((tempbh & 1) == 1) {
            tempbl |= 0x8000000000000000LL;
        }
        tempbh >>= 1;
    }
    long long ret;
    if((sa ^ sb)==0){
      ret = q;
    }else{
      ret = -q;
    }
    return ret;
}


unsigned long long __umoddi3(unsigned long long a, unsigned long long b){
    unsigned long long tempah = 0;
    unsigned long long tempal = a;

    unsigned long long tempbh = b;
    unsigned long long tempbl = 0;

    unsigned long long q = 0;
    int i;
    for (i = 0; i <= 64; i++)
    {
        q <<= 1;
        if ((tempah > tempbh) || (tempah == tempbh && tempal >= tempbl))
        {
            //tempa -= tempb;
            if (tempal < tempbl)
            {
                tempah--;
            }
            tempal -= tempbl;
            tempah -= tempbh;
            q++;
        }
        //tempb >>= 1;
        tempbl >>= 1;
        if ((tempbh & 1) == 1) {
            tempbl |= 0x8000000000000000LL;
        }
        tempbh >>= 1;
    }
    unsigned long long rem = tempal;
    return rem;
}

unsigned long long __udivdi3(unsigned long long a, unsigned long long b){
    unsigned long long tempah = 0;
    unsigned long long tempal = a;

    unsigned long long tempbh = b;
    unsigned long long tempbl = 0;

    unsigned long long q = 0;
    int i;
    for (i = 0; i <= 64; i++)
    {
        q <<= 1;
        if ((tempah > tempbh) || (tempah == tempbh && tempal >= tempbl))
        {
            //tempa -= tempb;
            if (tempal < tempbl)
            {
                tempah--;
            }
            tempal -= tempbl;
            tempah -= tempbh;
            q++;
        }
        //tempb >>= 1;
        tempbl >>= 1;
        if ((tempbh & 1) == 1) {
            tempbl |= 0x8000000000000000LL;
        }
        tempbh >>= 1;
    }
    return q;
}


//#include "double.h"

#if _FP_W_TYPE_SIZE < 32
#error "Here's a nickel kid.  Go buy yourself a real computer."
#endif

#if _FP_W_TYPE_SIZE < 64
#define _FP_FRACTBITS_D		(2 * _FP_W_TYPE_SIZE)
#else
#define _FP_FRACTBITS_D		_FP_W_TYPE_SIZE
#endif

#define _FP_FRACBITS_D		53
#define _FP_FRACXBITS_D		(_FP_FRACTBITS_D - _FP_FRACBITS_D)
#define _FP_WFRACBITS_D		(_FP_WORKBITS + _FP_FRACBITS_D)
#define _FP_WFRACXBITS_D	(_FP_FRACTBITS_D - _FP_WFRACBITS_D)
#define _FP_EXPBITS_D		11
#define _FP_EXPBIAS_D		1023
#define _FP_EXPMAX_D		2047

#define _FP_QNANBIT_D		\
	((_FP_W_TYPE)1 << (_FP_FRACBITS_D-2) % _FP_W_TYPE_SIZE)
#define _FP_QNANBIT_SH_D		\
	((_FP_W_TYPE)1 << (_FP_FRACBITS_D-2+_FP_WORKBITS) % _FP_W_TYPE_SIZE)
#define _FP_IMPLBIT_D		\
	((_FP_W_TYPE)1 << (_FP_FRACBITS_D-1) % _FP_W_TYPE_SIZE)
#define _FP_IMPLBIT_SH_D		\
	((_FP_W_TYPE)1 << (_FP_FRACBITS_D-1+_FP_WORKBITS) % _FP_W_TYPE_SIZE)
#define _FP_OVERFLOW_D		\
	((_FP_W_TYPE)1 << _FP_WFRACBITS_D % _FP_W_TYPE_SIZE)

typedef float DFtype __attribute__((mode(DF)));

#if _FP_W_TYPE_SIZE < 64

union _FP_UNION_D
{
  DFtype flt;
  struct _FP_STRUCT_LAYOUT {
#if __BYTE_ORDER == __BIG_ENDIAN
    unsigned sign  : 1;
    unsigned exp   : _FP_EXPBITS_D;
    unsigned frac1 : _FP_FRACBITS_D - (_FP_IMPLBIT_D != 0) - _FP_W_TYPE_SIZE;
    unsigned frac0 : _FP_W_TYPE_SIZE;
#else
    unsigned frac0 : _FP_W_TYPE_SIZE;
    unsigned frac1 : _FP_FRACBITS_D - (_FP_IMPLBIT_D != 0) - _FP_W_TYPE_SIZE;
    unsigned exp   : _FP_EXPBITS_D;
    unsigned sign  : 1;
#endif
  } bits __attribute__((packed));
};

#define FP_DECL_D(X)		_FP_DECL(2,X)
#define FP_UNPACK_RAW_D(X,val)	_FP_UNPACK_RAW_2(D,X,val)
#define FP_UNPACK_RAW_DP(X,val)	_FP_UNPACK_RAW_2_P(D,X,val)
#define FP_PACK_RAW_D(val,X)	_FP_PACK_RAW_2(D,val,X)
#define FP_PACK_RAW_DP(val,X)		\
  do {					\
    if (!FP_INHIBIT_RESULTS)		\
      _FP_PACK_RAW_2_P(D,val,X);	\
  } while (0)

#define FP_UNPACK_D(X,val)		\
  do {					\
    _FP_UNPACK_RAW_2(D,X,val);		\
    _FP_UNPACK_CANONICAL(D,2,X);	\
  } while (0)

#define FP_UNPACK_DP(X,val)		\
  do {					\
    _FP_UNPACK_RAW_2_P(D,X,val);	\
    _FP_UNPACK_CANONICAL(D,2,X);	\
  } while (0)

#define FP_UNPACK_SEMIRAW_D(X,val)	\
  do {					\
    _FP_UNPACK_RAW_2(D,X,val);		\
    _FP_UNPACK_SEMIRAW(D,2,X);		\
  } while (0)

#define FP_UNPACK_SEMIRAW_DP(X,val)	\
  do {					\
    _FP_UNPACK_RAW_2_P(D,X,val);	\
    _FP_UNPACK_SEMIRAW(D,2,X);		\
  } while (0)

#define FP_PACK_D(val,X)		\
  do {					\
    _FP_PACK_CANONICAL(D,2,X);		\
    _FP_PACK_RAW_2(D,val,X);		\
  } while (0)

#define FP_PACK_DP(val,X)		\
  do {					\
    _FP_PACK_CANONICAL(D,2,X);		\
    if (!FP_INHIBIT_RESULTS)		\
      _FP_PACK_RAW_2_P(D,val,X);	\
  } while (0)

#define FP_PACK_SEMIRAW_D(val,X)	\
  do {					\
    _FP_PACK_SEMIRAW(D,2,X);		\
    _FP_PACK_RAW_2(D,val,X);		\
  } while (0)

#define FP_PACK_SEMIRAW_DP(val,X)	\
  do {					\
    _FP_PACK_SEMIRAW(D,2,X);		\
    if (!FP_INHIBIT_RESULTS)		\
      _FP_PACK_RAW_2_P(D,val,X);	\
  } while (0)

#define FP_ISSIGNAN_D(X)		_FP_ISSIGNAN(D,2,X)
#define FP_NEG_D(R,X)			_FP_NEG(D,2,R,X)
#define FP_ADD_D(R,X,Y)			_FP_ADD(D,2,R,X,Y)
#define FP_SUB_D(R,X,Y)			_FP_SUB(D,2,R,X,Y)
#define FP_MUL_D(R,X,Y)			_FP_MUL(D,2,R,X,Y)
#define FP_DIV_D(R,X,Y)			_FP_DIV(D,2,R,X,Y)
#define FP_SQRT_D(R,X)			_FP_SQRT(D,2,R,X)
#define _FP_SQRT_MEAT_D(R,S,T,X,Q)	_FP_SQRT_MEAT_2(R,S,T,X,Q)

#define FP_CMP_D(r,X,Y,un)	_FP_CMP(D,2,r,X,Y,un)
#define FP_CMP_EQ_D(r,X,Y)	_FP_CMP_EQ(D,2,r,X,Y)
#define FP_CMP_UNORD_D(r,X,Y)	_FP_CMP_UNORD(D,2,r,X,Y)

#define FP_TO_INT_D(r,X,rsz,rsg)	_FP_TO_INT(D,2,r,X,rsz,rsg)
#define FP_FROM_INT_D(X,r,rs,rt)	_FP_FROM_INT(D,2,X,r,rs,rt)

#define _FP_FRAC_HIGH_D(X)	_FP_FRAC_HIGH_2(X)
#define _FP_FRAC_HIGH_RAW_D(X)	_FP_FRAC_HIGH_2(X)

#else

union _FP_UNION_D
{
  DFtype flt;
  struct _FP_STRUCT_LAYOUT {
#if __BYTE_ORDER == __BIG_ENDIAN
    unsigned sign   : 1;
    unsigned exp    : _FP_EXPBITS_D;
    _FP_W_TYPE frac : _FP_FRACBITS_D - (_FP_IMPLBIT_D != 0);
#else
    _FP_W_TYPE frac : _FP_FRACBITS_D - (_FP_IMPLBIT_D != 0);
    unsigned exp    : _FP_EXPBITS_D;
    unsigned sign   : 1;
#endif
  } bits __attribute__((packed));
};

#define FP_DECL_D(X)		_FP_DECL(1,X)
#define FP_UNPACK_RAW_D(X,val)	_FP_UNPACK_RAW_1(D,X,val)
#define FP_UNPACK_RAW_DP(X,val)	_FP_UNPACK_RAW_1_P(D,X,val)
#define FP_PACK_RAW_D(val,X)	_FP_PACK_RAW_1(D,val,X)
#define FP_PACK_RAW_DP(val,X)		\
  do {					\
    if (!FP_INHIBIT_RESULTS)		\
      _FP_PACK_RAW_1_P(D,val,X);	\
  } while (0)

#define FP_UNPACK_D(X,val)		\
  do {					\
    _FP_UNPACK_RAW_1(D,X,val);		\
    _FP_UNPACK_CANONICAL(D,1,X);	\
  } while (0)

#define FP_UNPACK_DP(X,val)		\
  do {					\
    _FP_UNPACK_RAW_1_P(D,X,val);	\
    _FP_UNPACK_CANONICAL(D,1,X);	\
  } while (0)

#define FP_UNPACK_SEMIRAW_D(X,val)	\
  do {					\
    _FP_UNPACK_RAW_1(D,X,val);		\
    _FP_UNPACK_SEMIRAW(D,1,X);		\
  } while (0)

#define FP_UNPACK_SEMIRAW_DP(X,val)	\
  do {					\
    _FP_UNPACK_RAW_1_P(D,X,val);	\
    _FP_UNPACK_SEMIRAW(D,1,X);		\
  } while (0)

#define FP_PACK_D(val,X)		\
  do {					\
    _FP_PACK_CANONICAL(D,1,X);		\
    _FP_PACK_RAW_1(D,val,X);		\
  } while (0)

#define FP_PACK_DP(val,X)		\
  do {					\
    _FP_PACK_CANONICAL(D,1,X);		\
    if (!FP_INHIBIT_RESULTS)		\
      _FP_PACK_RAW_1_P(D,val,X);	\
  } while (0)

#define FP_PACK_SEMIRAW_D(val,X)	\
  do {					\
    _FP_PACK_SEMIRAW(D,1,X);		\
    _FP_PACK_RAW_1(D,val,X);		\
  } while (0)

#define FP_PACK_SEMIRAW_DP(val,X)	\
  do {					\
    _FP_PACK_SEMIRAW(D,1,X);		\
    if (!FP_INHIBIT_RESULTS)		\
      _FP_PACK_RAW_1_P(D,val,X);	\
  } while (0)

#define FP_ISSIGNAN_D(X)		_FP_ISSIGNAN(D,1,X)
#define FP_NEG_D(R,X)			_FP_NEG(D,1,R,X)
#define FP_ADD_D(R,X,Y)			_FP_ADD(D,1,R,X,Y)
#define FP_SUB_D(R,X,Y)			_FP_SUB(D,1,R,X,Y)
#define FP_MUL_D(R,X,Y)			_FP_MUL(D,1,R,X,Y)
#define FP_DIV_D(R,X,Y)			_FP_DIV(D,1,R,X,Y)
#define FP_SQRT_D(R,X)			_FP_SQRT(D,1,R,X)
#define _FP_SQRT_MEAT_D(R,S,T,X,Q)	_FP_SQRT_MEAT_1(R,S,T,X,Q)

/* The implementation of _FP_MUL_D and _FP_DIV_D should be chosen by
   the target machine.  */

#define FP_CMP_D(r,X,Y,un)	_FP_CMP(D,1,r,X,Y,un)
#define FP_CMP_EQ_D(r,X,Y)	_FP_CMP_EQ(D,1,r,X,Y)
#define FP_CMP_UNORD_D(r,X,Y)	_FP_CMP_UNORD(D,1,r,X,Y)

#define FP_TO_INT_D(r,X,rsz,rsg)	_FP_TO_INT(D,1,r,X,rsz,rsg)
#define FP_FROM_INT_D(X,r,rs,rt)	_FP_FROM_INT(D,1,X,r,rs,rt)

#define _FP_FRAC_HIGH_D(X)	_FP_FRAC_HIGH_1(X)
#define _FP_FRAC_HIGH_RAW_D(X)	_FP_FRAC_HIGH_1(X)

#endif /* W_TYPE_SIZE < 64 */

//#include "single.h"

#if _FP_W_TYPE_SIZE < 32
#error "Here's a nickel kid.  Go buy yourself a real computer."
#endif

#define _FP_FRACTBITS_S		_FP_W_TYPE_SIZE

#define _FP_FRACBITS_S		24
#define _FP_FRACXBITS_S		(_FP_FRACTBITS_S - _FP_FRACBITS_S)
#define _FP_WFRACBITS_S		(_FP_WORKBITS + _FP_FRACBITS_S)
#define _FP_WFRACXBITS_S	(_FP_FRACTBITS_S - _FP_WFRACBITS_S)
#define _FP_EXPBITS_S		8
#define _FP_EXPBIAS_S		127
#define _FP_EXPMAX_S		255
#define _FP_QNANBIT_S		((_FP_W_TYPE)1 << (_FP_FRACBITS_S-2))
#define _FP_QNANBIT_SH_S	((_FP_W_TYPE)1 << (_FP_FRACBITS_S-2+_FP_WORKBITS))
#define _FP_IMPLBIT_S		((_FP_W_TYPE)1 << (_FP_FRACBITS_S-1))
#define _FP_IMPLBIT_SH_S	((_FP_W_TYPE)1 << (_FP_FRACBITS_S-1+_FP_WORKBITS))
#define _FP_OVERFLOW_S		((_FP_W_TYPE)1 << (_FP_WFRACBITS_S))

/* The implementation of _FP_MUL_MEAT_S and _FP_DIV_MEAT_S should be
   chosen by the target machine.  */

typedef float SFtype __attribute__((mode(SF)));

union _FP_UNION_S
{
  SFtype flt;
  struct _FP_STRUCT_LAYOUT {
#if __BYTE_ORDER == __BIG_ENDIAN
    unsigned sign : 1;
    unsigned exp  : _FP_EXPBITS_S;
    unsigned frac : _FP_FRACBITS_S - (_FP_IMPLBIT_S != 0);
#else
    unsigned frac : _FP_FRACBITS_S - (_FP_IMPLBIT_S != 0);
    unsigned exp  : _FP_EXPBITS_S;
    unsigned sign : 1;
#endif
  } bits __attribute__((packed));
};

#define FP_DECL_S(X)		_FP_DECL(1,X)
#define FP_UNPACK_RAW_S(X,val)	_FP_UNPACK_RAW_1(S,X,val)
#define FP_UNPACK_RAW_SP(X,val)	_FP_UNPACK_RAW_1_P(S,X,val)
#define FP_PACK_RAW_S(val,X)	_FP_PACK_RAW_1(S,val,X)
#define FP_PACK_RAW_SP(val,X)		\
  do {					\
    if (!FP_INHIBIT_RESULTS)		\
      _FP_PACK_RAW_1_P(S,val,X);	\
  } while (0)

#define FP_UNPACK_S(X,val)		\
  do {					\
    _FP_UNPACK_RAW_1(S,X,val);		\
    _FP_UNPACK_CANONICAL(S,1,X);	\
  } while (0)

#define FP_UNPACK_SP(X,val)		\
  do {					\
    _FP_UNPACK_RAW_1_P(S,X,val);	\
    _FP_UNPACK_CANONICAL(S,1,X);	\
  } while (0)

#define FP_UNPACK_SEMIRAW_S(X,val)	\
  do {					\
    _FP_UNPACK_RAW_1(S,X,val);		\
    _FP_UNPACK_SEMIRAW(S,1,X);		\
  } while (0)

#define FP_UNPACK_SEMIRAW_SP(X,val)	\
  do {					\
    _FP_UNPACK_RAW_1_P(S,X,val);	\
    _FP_UNPACK_SEMIRAW(S,1,X);		\
  } while (0)

#define FP_PACK_S(val,X)		\
  do {					\
    _FP_PACK_CANONICAL(S,1,X);		\
    _FP_PACK_RAW_1(S,val,X);		\
  } while (0)

#define FP_PACK_SP(val,X)		\
  do {					\
    _FP_PACK_CANONICAL(S,1,X);		\
    if (!FP_INHIBIT_RESULTS)		\
      _FP_PACK_RAW_1_P(S,val,X);	\
  } while (0)

#define FP_PACK_SEMIRAW_S(val,X)	\
  do {					\
    _FP_PACK_SEMIRAW(S,1,X);		\
    _FP_PACK_RAW_1(S,val,X);		\
  } while (0)

#define FP_PACK_SEMIRAW_SP(val,X)	\
  do {					\
    _FP_PACK_SEMIRAW(S,1,X);		\
    if (!FP_INHIBIT_RESULTS)		\
      _FP_PACK_RAW_1_P(S,val,X);	\
  } while (0)

#define FP_ISSIGNAN_S(X)		_FP_ISSIGNAN(S,1,X)
#define FP_NEG_S(R,X)			_FP_NEG(S,1,R,X)
#define FP_ADD_S(R,X,Y)			_FP_ADD(S,1,R,X,Y)
#define FP_SUB_S(R,X,Y)			_FP_SUB(S,1,R,X,Y)
#define FP_MUL_S(R,X,Y)			_FP_MUL(S,1,R,X,Y)
#define FP_DIV_S(R,X,Y)			_FP_DIV(S,1,R,X,Y)
#define FP_SQRT_S(R,X)			_FP_SQRT(S,1,R,X)
#define _FP_SQRT_MEAT_S(R,S,T,X,Q)	_FP_SQRT_MEAT_1(R,S,T,X,Q)

#define FP_CMP_S(r,X,Y,un)	_FP_CMP(S,1,r,X,Y,un)
#define FP_CMP_EQ_S(r,X,Y)	_FP_CMP_EQ(S,1,r,X,Y)
#define FP_CMP_UNORD_S(r,X,Y)	_FP_CMP_UNORD(S,1,r,X,Y)

#define FP_TO_INT_S(r,X,rsz,rsg)	_FP_TO_INT(S,1,r,X,rsz,rsg)
#define FP_FROM_INT_S(X,r,rs,rt)	_FP_FROM_INT(S,1,X,r,rs,rt)

#define _FP_FRAC_HIGH_S(X)	_FP_FRAC_HIGH_1(X)
#define _FP_FRAC_HIGH_RAW_S(X)	_FP_FRAC_HIGH_1(X)

typedef int word_type __attribute__ ((mode (__word__)));

struct DWstruct {
	int low, high;
};

typedef union {
	struct DWstruct s;
	long long ll;
} DWunion;











typedef struct {
	unsigned int l;
	unsigned int h;
} S64bit;

typedef union {
	DFtype df;
	unsigned long long ll;
	S64bit s;
} U64bit;

typedef union {
	SFtype sf;
	unsigned int s;
} U32bit;


unsigned long long __muldi3(unsigned long long a, unsigned long long b){
  #ifdef HARD_MUL
  U64bit aa;
  U64bit bb;
  aa.ll = a;
  bb.ll = b;
  IOWR(FPU, FPU_A_L, aa.s.l);
  IOWR(FPU, FPU_A_H, aa.s.h);
  IOWR(FPU, FPU_B_L, bb.s.l);
  IOWR(FPU, FPU_B_H, bb.s.h);
  
  
  U64bit result;
  result.s.l = IORD(FPU, FPU_MUL_RESULT_L);
  result.s.h = IORD(FPU, FPU_MUL_RESULT_H);
  return result.ll;
  #else
  unsigned long long result = 0;
  unsigned long long aa = a;
  unsigned long long bb = b;
  int i;
  for(i=0;i<64;i++){
    if(aa & 1){
      result += bb;
    }
    aa>>=1;
    bb<<=1;
  }
  return result;
  #endif
}














long long __ashldi3(long long u, word_type b)
{
  DWunion uu, w;
  word_type bm;

  if (b == 0)
          return u;

  uu.ll = u;
  bm = 32 - b;

  if (bm <= 0) {
    w.s.low = 0;
    w.s.high = (unsigned int) uu.s.low << -bm;
  } else {
    const unsigned int carries = (unsigned int) uu.s.low >> bm;

    w.s.low = (unsigned int) uu.s.low << b;
    w.s.high = ((unsigned int) uu.s.high << b) | carries;
  }

  return w.ll;
}

long long __lshrdi3(long long u, word_type b)
{
	DWunion uu, w;
	word_type bm;
	if (b == 0)
		return u;
	uu.ll = u;
	bm = 32 - b;
	if (bm <= 0) {
		w.s.high = 0;
		w.s.low = (unsigned int) uu.s.high >> -bm;
	} else {
		const unsigned int carries = (unsigned int) uu.s.high << bm;
		w.s.high = (unsigned int) uu.s.high >> b;
		w.s.low = ((unsigned int) uu.s.low >> b) | carries;
	}
	return w.ll;
}

DFtype __adddf3(DFtype a, DFtype b)
{
  FP_DECL_EX;
  FP_DECL_D(A); FP_DECL_D(B); FP_DECL_D(R);
  DFtype r;

  FP_INIT_ROUNDMODE;
  FP_UNPACK_SEMIRAW_D(A, a);
  FP_UNPACK_SEMIRAW_D(B, b);
  FP_ADD_D(R, A, B);
  FP_PACK_SEMIRAW_D(r, R);
  FP_HANDLE_EXCEPTIONS;

  return r;
}

SFtype __addsf3(SFtype a, SFtype b)
{
  FP_DECL_EX;
  FP_DECL_S(A); FP_DECL_S(B); FP_DECL_S(R);
  SFtype r;

  FP_INIT_ROUNDMODE;
  FP_UNPACK_SEMIRAW_S(A, a);
  FP_UNPACK_SEMIRAW_S(B, b);
  FP_ADD_S(R, A, B);
  FP_PACK_SEMIRAW_S(r, R);
  FP_HANDLE_EXCEPTIONS;

  return r;
}

// Returns: the number of leading 0-bits
// Precondition: a != 0
unsigned int __clzsi2(unsigned int a)
{
    unsigned int x = a;
    int t = ((x & 0xFFFF0000) == 0) << 4;  // if (x is small) t = 16 else 0
    x >>= 16 - t;      // x = [0 - 0xFFFF]
    unsigned int r = t;       // r = [0, 16]
    // return r + clz(x)
    t = ((x & 0xFF00) == 0) << 3;
    x >>= 8 - t;       // x = [0 - 0xFF]
    r += t;            // r = [0, 8, 16, 24]
    // return r + clz(x)
    t = ((x & 0xF0) == 0) << 2;
    x >>= 4 - t;       // x = [0 - 0xF]
    r += t;            // r = [0, 4, 8, 12, 16, 20, 24, 28]
    // return r + clz(x)
    t = ((x & 0xC) == 0) << 1;
    x >>= 2 - t;       // x = [0 - 3]
    r += t;            // r = [0 - 30] and is even
    // return r + clz(x)
//     switch (x)
//     {
//     case 0:
//         return r + 2;
//     case 1:
//         return r + 1;
//     case 2:
//     case 3:
//         return r;
//     }
    return r + ((2 - x) & -((x & 2) == 0));
}

DFtype __divdf3(DFtype a, DFtype b)
{
  #ifdef HARD_FDIV
  U64bit aa;
  U64bit bb;
  aa.df = a;
  bb.df = b;
  IOWR(FPU, FPU_A_L, aa.s.l);
  IOWR(FPU, FPU_A_H, aa.s.h);
  IOWR(FPU, FPU_B_L, bb.s.l);
  IOWR(FPU, FPU_B_H, bb.s.h);
  
  
  U64bit result;
  result.s.l = IORD(FPU, FPU_FDIV_RESULT_L);
  result.s.h = IORD(FPU, FPU_FDIV_RESULT_H);
  return result.df;

  #else
  FP_DECL_EX;
  FP_DECL_D(A); FP_DECL_D(B); FP_DECL_D(R);
  DFtype r;

  FP_INIT_ROUNDMODE;
  FP_UNPACK_D(A, a);
  FP_UNPACK_D(B, b);
  FP_DIV_D(R, A, B);
  FP_PACK_D(r, R);
  FP_HANDLE_EXCEPTIONS;

  return r;
  #endif
}

SFtype __divsf3(SFtype a, SFtype b)
{
  #ifdef HARD_SFDIV
  U32bit aa;
  U32bit bb;
  aa.sf = a;
  bb.sf = b;
  IOWR(FPU, FPU_A_L, aa.s);
  IOWR(FPU, FPU_B_L, bb.s);
  
  
  U32bit result;
  result.s = IORD(FPU, FPU_SFDIV_RESULT);
  return result.sf;

  #else
  FP_DECL_EX;
  FP_DECL_S(A); FP_DECL_S(B); FP_DECL_S(R);
  SFtype r;

  FP_INIT_ROUNDMODE;
  FP_UNPACK_S(A, a);
  FP_UNPACK_S(B, b);
  FP_DIV_S(R, A, B);
  FP_PACK_S(r, R);
  FP_HANDLE_EXCEPTIONS;

  return r;
  #endif
}

CMPtype __eqdf2(DFtype a, DFtype b)
{
  FP_DECL_EX;
  FP_DECL_D(A); FP_DECL_D(B);
  CMPtype r;

  FP_UNPACK_RAW_D(A, a);
  FP_UNPACK_RAW_D(B, b);
  FP_CMP_EQ_D(r, A, B);
  if (r && (FP_ISSIGNAN_D(A) || FP_ISSIGNAN_D(B)))
    FP_SET_EXCEPTION(FP_EX_INVALID);
  FP_HANDLE_EXCEPTIONS;

  return r;
}


CMPtype __eqsf2(SFtype a, SFtype b)
{
  FP_DECL_EX;
  FP_DECL_S(A); FP_DECL_S(B);
  CMPtype r;

  FP_UNPACK_RAW_S(A, a);
  FP_UNPACK_RAW_S(B, b);
  FP_CMP_EQ_S(r, A, B);
  if (r && (FP_ISSIGNAN_S(A) || FP_ISSIGNAN_S(B)))
    FP_SET_EXCEPTION(FP_EX_INVALID);
  FP_HANDLE_EXCEPTIONS;

  return r;
}

/*   
   Return a converted to IEEE double
       */

DFtype __extendsfdf2(SFtype a)
{
  FP_DECL_EX;
  FP_DECL_S(A);
  FP_DECL_D(R);
  DFtype r;

  FP_INIT_ROUNDMODE;
  FP_UNPACK_RAW_S(A, a);
#if _FP_W_TYPE_SIZE < _FP_FRACBITS_D
  FP_EXTEND(D,S,2,1,R,A);
#else
  FP_EXTEND(D,S,1,1,R,A);
#endif
  FP_PACK_RAW_D(r, R);
  FP_HANDLE_EXCEPTIONS;

  return r;
}
/*   
   Convert a to 64bit signed integer
    
       */

DItype __fixdfdi(DFtype a)
{
  FP_DECL_EX;
  FP_DECL_D(A);
  UDItype r;

  FP_UNPACK_RAW_D(A, a);
  FP_TO_INT_D(r, A, DI_BITS, 1);
  FP_HANDLE_EXCEPTIONS;

  return r;
}
/*   
   Convert a to 32bit signed integer
     
     
     
     
     
       */


SItype __fixdfsi(DFtype a)
{
  FP_DECL_EX;
  FP_DECL_D(A);
  USItype r;

  FP_UNPACK_RAW_D(A, a);
  FP_TO_INT_D(r, A, SI_BITS, 1);
  FP_HANDLE_EXCEPTIONS;

  return r;
}
/*   
   Convert a to 64bit signed integer
     
       */

DItype __fixsfdi(SFtype a)
{
  FP_DECL_EX;
  FP_DECL_S(A);
  UDItype r;

  FP_UNPACK_RAW_S(A, a);
  FP_TO_INT_S(r, A, DI_BITS, 1);
  FP_HANDLE_EXCEPTIONS;

  return r;
}
/*   
   Convert a to 32bit signed integer
     
     
       */

SItype __fixsfsi(SFtype a)
{
  FP_DECL_EX;
  FP_DECL_S(A);
  USItype r;

  FP_UNPACK_RAW_S(A, a);
  FP_TO_INT_S(r, A, SI_BITS, 1);
  FP_HANDLE_EXCEPTIONS;

  return r;
}

/*   
   Convert a to 64bit unsigned integer

       */

UDItype __fixunsdfdi(DFtype a)
{
  FP_DECL_EX;
  FP_DECL_D(A);
  UDItype r;

  FP_UNPACK_RAW_D(A, a);
  FP_TO_INT_D(r, A, DI_BITS, 0);
  FP_HANDLE_EXCEPTIONS;

  return r;
}
/*   
   Convert a to 32bit unsigned integer
     
     
     
		    

     
     
     
     

     
     
     
     
     
     
     
     

     
     
     
     

     
     
       */

  
  

USItype __fixunsdfsi(DFtype a)
{
  FP_DECL_EX;
  FP_DECL_D(A);
  USItype r;

  FP_UNPACK_RAW_D(A, a);
  FP_TO_INT_D(r, A, SI_BITS, 0);
  FP_HANDLE_EXCEPTIONS;

  return r;
}
/*   
   Convert a to 64bit unsigned integer
     
     
     
		    

     
     
     
     

     
     
     
     
     
     
     
     

     
     
     
     

     
     
       */

  
  

UDItype __fixunssfdi(SFtype a)
{
  FP_DECL_EX;
  FP_DECL_S(A);
  UDItype r;

  FP_UNPACK_RAW_S(A, a);
  FP_TO_INT_S(r, A, DI_BITS, 0);
  FP_HANDLE_EXCEPTIONS;

  return r;
}
/*   
   Convert a to 32bit unsigned integer
     
     
     
		    

     
     
     
     

     
     
     
     
     
     
     
     

     
     
     
     

     
     
       */

  
  

USItype __fixunssfsi(SFtype a)
{
  FP_DECL_EX;
  FP_DECL_S(A);
  USItype r;

  FP_UNPACK_RAW_S(A, a);
  FP_TO_INT_S(r, A, SI_BITS, 0);
  FP_HANDLE_EXCEPTIONS;

  return r;
}
/*   
   Convert a 64bit signed integer to IEEE double
     
     
     
       */

  
  

DFtype __floatdidf(DItype i)
{
  FP_DECL_EX;
  FP_DECL_D(A);
  DFtype a;

  FP_FROM_INT_D(A, i, DI_BITS, UDItype);
  FP_PACK_RAW_D(a, A);
  FP_HANDLE_EXCEPTIONS;

  return a;
}
/*   
   Convert a 64bit signed integer to IEEE single
     
     
     
		    

     
     
     
     

     
     
     
     
     
     
     
     

     
     
     
     

     
     
       */

  
  

SFtype __floatdisf(DItype i)
{
  FP_DECL_EX;
  FP_DECL_S(A);
  SFtype a;

  FP_FROM_INT_S(A, i, DI_BITS, UDItype);
  FP_PACK_RAW_S(a, A);
  FP_HANDLE_EXCEPTIONS;

  return a;
}
/*   
   Convert a 32bit signed integer to IEEE double
     
     
     
		    

     
     
     
     

     
     
     
     
     
     
     
     

     
     
     
     

     
     
       */

  
  

DFtype __floatsidf(SItype i)
{
  FP_DECL_EX;
  FP_DECL_D(A);
  DFtype a;

  FP_FROM_INT_D(A, i, SI_BITS, USItype);
  FP_PACK_RAW_D(a, A);
  FP_HANDLE_EXCEPTIONS;

  return a;
}
/*   
   Convert a 32bit signed integer to IEEE single
     
     
     
		    

     
     
     
     

     
     
     
     
     
     
     
     

     
     
     
     

     
     
       */

  
  

SFtype __floatsisf(SItype i)
{
  FP_DECL_EX;
  FP_DECL_S(A);
  SFtype a;

  FP_FROM_INT_S(A, i, SI_BITS, USItype);
  FP_PACK_RAW_S(a, A);
  FP_HANDLE_EXCEPTIONS;

  return a;
}
/*   
   Convert a 64bit unsigned integer to IEEE double
   Copyright (C) 1997, 1999, 2006, 2007 Free Software Foundation, Inc.
     
     
		    

     
     
     
     

     
     
     
     
     
     
     
     

     
     
     
     

     
     
       */

  
  

DFtype __floatundidf(UDItype i)
{
  FP_DECL_EX;
  FP_DECL_D(A);
  DFtype a;

  FP_FROM_INT_D(A, i, DI_BITS, UDItype);
  FP_PACK_RAW_D(a, A);
  FP_HANDLE_EXCEPTIONS;

  return a;
}
/*   
   Convert a 64bit unsigned integer to IEEE single
   Copyright (C) 1997, 1999, 2006, 2007 Free Software Foundation, Inc.
     
     
		    

     
     
     
     

     
     
     
     
     
     
     
     

     
     
     
     

     
     
       */

  
  

SFtype __floatundisf(UDItype i)
{
  FP_DECL_EX;
  FP_DECL_S(A);
  SFtype a;

  FP_FROM_INT_S(A, i, DI_BITS, UDItype);
  FP_PACK_RAW_S(a, A);
  FP_HANDLE_EXCEPTIONS;

  return a;
}
/*   
   Convert a 32bit unsigned integer to IEEE double
   Copyright (C) 1997, 1999, 2006, 2007 Free Software Foundation, Inc.
     
     
		    

     
     
     
     

     
     
     
     
     
     
     
     

     
     
     
     

     
     
       */

  
  

DFtype __floatunsidf(USItype i)
{
  FP_DECL_EX;
  FP_DECL_D(A);
  DFtype a;

  FP_FROM_INT_D(A, i, SI_BITS, USItype);
  FP_PACK_RAW_D(a, A);
  FP_HANDLE_EXCEPTIONS;

  return a;
}
/*   
   Convert a 32bit unsigned integer to IEEE single
   Copyright (C) 1997, 1999, 2006, 2007 Free Software Foundation, Inc.
     
     
		    

     
     
     
     

     
     
     
     
     
     
     
     

     
     
     
     

     
     
       */

  
  

SFtype __floatunsisf(USItype i)
{
  FP_DECL_EX;
  FP_DECL_S(A);
  SFtype a;

  FP_FROM_INT_S(A, i, SI_BITS, USItype);
  FP_PACK_RAW_S(a, A);
  FP_HANDLE_EXCEPTIONS;

  return a;
}
/*   
   Return 0 iff a == b, 1 iff a > b, -2 iff a ? b, -1 iff a < b
   Copyright (C) 1997,1999,2006,2007 Free Software Foundation, Inc.
     
     
		    

     
     
     
     

     
     
     
     
     
     
     
     

     
     
     
     

     
     
       */

  
  
//strong_alias(__gedf2, __gtdf2);
CMPtype __gedf2(DFtype a, DFtype b)
{
  FP_DECL_EX;
  FP_DECL_D(A); FP_DECL_D(B);
  CMPtype r;

  FP_UNPACK_RAW_D(A, a);
  FP_UNPACK_RAW_D(B, b);
  FP_CMP_D(r, A, B, -2);
  if (r == -2 && (FP_ISSIGNAN_D(A) || FP_ISSIGNAN_D(B)))
    FP_SET_EXCEPTION(FP_EX_INVALID);
  FP_HANDLE_EXCEPTIONS;

  return r;
}
CMPtype __gtdf2(DFtype a, DFtype b)
{
  FP_DECL_EX;
  FP_DECL_D(A); FP_DECL_D(B);
  CMPtype r;

  FP_UNPACK_RAW_D(A, a);
  FP_UNPACK_RAW_D(B, b);
  FP_CMP_D(r, A, B, -2);
  if (r == -2 && (FP_ISSIGNAN_D(A) || FP_ISSIGNAN_D(B)))
    FP_SET_EXCEPTION(FP_EX_INVALID);
  FP_HANDLE_EXCEPTIONS;

  return r;
}

/*   
   Return 0 iff a == b, 1 iff a > b, -2 iff a ? b, -1 iff a < b
       */

  
  

CMPtype __gesf2(SFtype a, SFtype b)
{
  FP_DECL_EX;
  FP_DECL_S(A); FP_DECL_S(B);
  CMPtype r;

  FP_UNPACK_RAW_S(A, a);
  FP_UNPACK_RAW_S(B, b);
  FP_CMP_S(r, A, B, -2);
  if (r == -2 && (FP_ISSIGNAN_S(A) || FP_ISSIGNAN_S(B)))
    FP_SET_EXCEPTION(FP_EX_INVALID);
  FP_HANDLE_EXCEPTIONS;

  return r;
}

/*   
   Return 0 iff a == b, 1 iff a > b, 2 iff a ? b, -1 iff a < b
     
     
       */

  
  

CMPtype __ltdf2(DFtype a, DFtype b)
{
  FP_DECL_EX;
  FP_DECL_D(A); FP_DECL_D(B);
  CMPtype r;

  FP_UNPACK_RAW_D(A, a);
  FP_UNPACK_RAW_D(B, b);
  FP_CMP_D(r, A, B, 2);
  if (r == 2 && (FP_ISSIGNAN_D(A) || FP_ISSIGNAN_D(B)))
    FP_SET_EXCEPTION(FP_EX_INVALID);
  FP_HANDLE_EXCEPTIONS;

  return r;
}
//==
CMPtype __ledf2(DFtype a, DFtype b)
{
  FP_DECL_EX;
  FP_DECL_D(A); FP_DECL_D(B);
  CMPtype r;

  FP_UNPACK_RAW_D(A, a);
  FP_UNPACK_RAW_D(B, b);
  FP_CMP_D(r, A, B, 2);
  if (r == 2 && (FP_ISSIGNAN_D(A) || FP_ISSIGNAN_D(B)))
    FP_SET_EXCEPTION(FP_EX_INVALID);
  FP_HANDLE_EXCEPTIONS;

  return r;
}

/*   
   Return 0 iff a == b, 1 iff a > b, 2 iff a ? b, -1 iff a < b
   Copyright (C) 1997,1999,2006,2007 Free Software Foundation, Inc.
     
     
       */

  
  

CMPtype __lesf2(SFtype a, SFtype b)
{
  FP_DECL_EX;
  FP_DECL_S(A); FP_DECL_S(B);
  CMPtype r;

  FP_UNPACK_RAW_S(A, a);
  FP_UNPACK_RAW_S(B, b);
  FP_CMP_S(r, A, B, 2);
  if (r == 2 && (FP_ISSIGNAN_S(A) || FP_ISSIGNAN_S(B)))
    FP_SET_EXCEPTION(FP_EX_INVALID);
  FP_HANDLE_EXCEPTIONS;

  return r;
}

/*   
   Return a * b
       */

DFtype __muldf3(DFtype a, DFtype b)
{
  #ifdef HARD_FMUL
  U64bit aa;
  U64bit bb;
  aa.df = a;
  bb.df = b;
  IOWR(FPU, FPU_A_L, aa.s.l);
  IOWR(FPU, FPU_A_H, aa.s.h);
  IOWR(FPU, FPU_B_L, bb.s.l);
  IOWR(FPU, FPU_B_H, bb.s.h);
  
  
  U64bit result;
  result.s.l = IORD(FPU, FPU_FMUL_RESULT_L);
  result.s.h = IORD(FPU, FPU_FMUL_RESULT_H);
  return result.df;

  #else
  FP_DECL_EX;
  FP_DECL_D(A); FP_DECL_D(B); FP_DECL_D(R);
  DFtype r;

  FP_INIT_ROUNDMODE;
  FP_UNPACK_D(A, a);
  FP_UNPACK_D(B, b);
  FP_MUL_D(R, A, B);
  FP_PACK_D(r, R);
  FP_HANDLE_EXCEPTIONS;

  return r;
  #endif
}
/*   
   Return a * b
       */


SFtype __mulsf3(SFtype a, SFtype b)
{
  #ifdef HARD_SFMUL
  U32bit aa;
  U32bit bb;
  aa.sf = a;
  bb.sf = b;
  IOWR(FPU, FPU_A_L, aa.s);
  IOWR(FPU, FPU_B_L, bb.s);
  
  
  U32bit result;
  result.s = IORD(FPU, FPU_SFMUL_RESULT);
  return result.sf;

  #else

  FP_DECL_EX;
  FP_DECL_S(A); FP_DECL_S(B); FP_DECL_S(R);
  SFtype r;

  FP_INIT_ROUNDMODE;
  FP_UNPACK_S(A, a);
  FP_UNPACK_S(B, b);
  FP_MUL_S(R, A, B);
  FP_PACK_S(r, R);
  FP_HANDLE_EXCEPTIONS;

  return r;
  #endif
}
/*   
   Return -a
     
       */

  
  

DFtype __negdf2(DFtype a)
{
  FP_DECL_EX;
  FP_DECL_D(A); FP_DECL_D(R);
  DFtype r;

  FP_UNPACK_D(A, a);
  FP_NEG_D(R, A);
  FP_PACK_D(r, R);
  FP_CLEAR_EXCEPTIONS;
  FP_HANDLE_EXCEPTIONS;

  return r;
}
/*   
   Return -a
     
     
     
		    

     
     
     
     

     
     
     
     
     
     
     
     

     
     
     
     

     
     
       */

  
  

SFtype __negsf2(SFtype a)
{
  FP_DECL_EX;
  FP_DECL_S(A); FP_DECL_S(R);
  SFtype r;

  FP_UNPACK_S(A, a);
  FP_NEG_S(R, A);
  FP_PACK_S(r, R);
  FP_CLEAR_EXCEPTIONS;
  FP_HANDLE_EXCEPTIONS;

  return r;
}
/*   
   Return sqrt(a)
     
     
     
		    

     
     
     
     

     
     
     
     
     
     
     
     

     
     
     
     

     
     
       */

  
  

DFtype __sqrtdf2(DFtype a)
{
  FP_DECL_EX;
  FP_DECL_D(A); FP_DECL_D(R);
  DFtype r;

  FP_INIT_ROUNDMODE;
  FP_UNPACK_D(A, a);
  FP_SQRT_D(R, A);
  FP_PACK_D(r, R);
  FP_HANDLE_EXCEPTIONS;

  return r;
}
/*   
   Return sqrt(a)
     
     
     
		    

     
     
     
     

     
     
     
     
     
     
     
     

     
     
     
     

     
     
       */

  
  

SFtype __sqrtsf2(SFtype a)
{
  FP_DECL_EX;
  FP_DECL_S(A); FP_DECL_S(R);
  SFtype r;

  FP_INIT_ROUNDMODE;
  FP_UNPACK_S(A, a);
  FP_SQRT_S(R, A);
  FP_PACK_S(r, R);
  FP_HANDLE_EXCEPTIONS;

  return r;
}
/*   
   Return a - b
     
     
     
		    

     
     
     
     

     
     
     
     
     
     
     
     

     
     
     
     

     
     
       */

  
  

DFtype __subdf3(DFtype a, DFtype b)
{
  FP_DECL_EX;
  FP_DECL_D(A); FP_DECL_D(B); FP_DECL_D(R);
  DFtype r;

  FP_INIT_ROUNDMODE;
  FP_UNPACK_SEMIRAW_D(A, a);
  FP_UNPACK_SEMIRAW_D(B, b);
  FP_SUB_D(R, A, B);
  FP_PACK_SEMIRAW_D(r, R);
  FP_HANDLE_EXCEPTIONS;

  return r;
}
/*   
   Return a - b
     
     
     
		    

     
     
     
     

     
     
     
     
     
     
     
     

     
     
     
     

     
     
       */

  
  

SFtype __subsf3(SFtype a, SFtype b)
{
  FP_DECL_EX;
  FP_DECL_S(A); FP_DECL_S(B); FP_DECL_S(R);
  SFtype r;

  FP_INIT_ROUNDMODE;
  FP_UNPACK_SEMIRAW_S(A, a);
  FP_UNPACK_SEMIRAW_S(B, b);
  FP_SUB_S(R, A, B);
  FP_PACK_SEMIRAW_S(r, R);
  FP_HANDLE_EXCEPTIONS;

  return r;
}
/*   
   Truncate IEEE double into IEEE single
     
     
     
		    

     
     
     
     

     
     
     
     
     
     
     
     

     
     
     
     

     
     
       */

  
  
  

SFtype __truncdfsf2(DFtype a)
{
  FP_DECL_EX;
  FP_DECL_D(A);
  FP_DECL_S(R);
  SFtype r;

  FP_INIT_ROUNDMODE;
  FP_UNPACK_SEMIRAW_D(A, a);
#if _FP_W_TYPE_SIZE < _FP_FRACBITS_D
  FP_TRUNC(S,D,1,2,R,A);
#else
  FP_TRUNC(S,D,1,1,R,A);
#endif
  FP_PACK_SEMIRAW_S(r, R);
  FP_HANDLE_EXCEPTIONS;

  return r;
}

/*   
   Return 1 iff a or b is a NaN, 0 otherwise.
       */
CMPtype __unorddf2(DFtype a, DFtype b)
{
  FP_DECL_D(A); FP_DECL_D(B);
  CMPtype r;

  FP_UNPACK_RAW_D(A, a);
  FP_UNPACK_RAW_D(B, b);
  FP_CMP_UNORD_D(r, A, B);

  return r;
}
/*   
   Return 1 iff a or b is a NaN, 0 otherwise.
       */

CMPtype __unordsf2(SFtype a, SFtype b)
{
  FP_DECL_S(A);
  FP_DECL_S(B);
  CMPtype r;

  FP_UNPACK_RAW_S(A, a);
  FP_UNPACK_RAW_S(B, b);
  FP_CMP_UNORD_S(r, A, B);

  return r;
}

//strong_alias(__eqdf2, __nedf2);
//strong_alias(__eqsf2, __nesf2);
//strong_alias(__lesf2, __ltsf2);
//strong_alias(__gesf2, __gtsf2);
//strong_alias(__ledf2, __ltdf2);

#define PI2 6.2831853071795862
#define PIhalf 1.5707963267948966
//3.141592653589793
double sin(double val)
{
    if(val > PI2){
        int count = (int)(val / PI2);
        val -= PI2 * count;
    }
    if (val < -PI2)
    {
        int count = (int)(-val / PI2);
        val += PI2 * count;
    }
    double ret = val;
    double num = val;
    double num_i = 1;
    double num_a = num;
    double num_b = 1;
    double num_x2 = num * num;
    double num2 = 1;
    double lastret = 0;
    int i;
    for (i = 1; i<100; i++)
    {
        num_a = num_a * num_x2;
        num_i = num_i + 1;
        num_b = num_b * num_i;
        num_i = num_i + 1;
        num_b = num_b * num_i;
        num2 = num_a / num_b;
        if ((i & 1) == 1)
        {
            num2 = -num2;
        }
        ret = ret + num2;
        if (i!=0 && ret == lastret) {
            break;
        }
        lastret = ret;
    }
    return ret;
}
double cos(double val)
{
   return sin(val + PIhalf);
}
